返回

SimpleDateFormat坑:规避日期校验的罕见姿势

后端

前言

在Java中,SimpleDateFormat类提供了对日期和时间的格式化和解析功能。它是一种广泛使用的日期处理工具,可以轻松地将日期和时间转换为指定格式的字符串,或将字符串解析为日期和时间对象。

问题背景

在最近的需求开发中,笔者遇到需要将给定目标数据通过某一固定的计量规则进行过滤并打标生成明细数据。其中发现存在一笔目标数据的时间在不符合现有日期规则的条件下,还是通过了规则引入明细数据表中。

问题分析

经过排查,发现问题出在SimpleDateFormat的日期校验上。在SimpleDateFormat中,当日期字符串不符合指定格式时,它不会抛出异常,而是会默默地将日期字符串解析为一个默认值。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse("2023-02-30"); // 20232月只有28System.out.println(date); // 输出: Wed Mar 01 00:00:00 CST 2023

在上面的代码中,由于"2023-02-30"这个日期字符串不符合"yyyy-MM-dd"格式,SimpleDateFormat不会抛出异常,而是将它解析为默认值"2023-03-01"。这导致了日期校验失败,不符合日期规则的数据也被错误地引入明细数据表中。

解决方案

要解决这个问题,有两种方法:

  1. 使用严格的日期校验规则。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setLenient(false); // 设置严格的日期校验规则
Date date = sdf.parse("2023-02-30"); // 抛出ParseException异常

在上面的代码中,通过设置sdf.setLenient(false),我们可以让SimpleDateFormat在遇到不符合格式的日期字符串时抛出ParseException异常。这样就可以在代码中捕获异常,并对不符合规则的数据进行处理。

  1. 使用Java 8中的日期时间API。

Java 8中引入了新的日期时间API,它提供了更强大的日期和时间处理功能。在Java 8中,我们可以使用LocalDateLocalDateTime等类来表示日期和时间,并使用DateTimeFormatter类来进行日期和时间的格式化和解析。

LocalDate date = LocalDate.parse("2023-02-30"); // 抛出DateTimeParseException异常

在上面的代码中,由于"2023-02-30"这个日期字符串不符合"yyyy-MM-dd"格式,LocalDate.parse()方法会抛出DateTimeParseException异常。这样就可以在代码中捕获异常,并对不符合规则的数据进行处理。

总结

SimpleDateFormat在日期处理中是一个非常有用的工具,但它也存在一些潜在的陷阱。在使用SimpleDateFormat时,一定要注意日期校验的规则,避免出现日期校验失败的问题。