java.util.Date 对象是否验证日期有效性?

Does the java.util.Date object verifies the date validity?

我刚刚写了这个单元测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void testGetDateFromString() throws ParseException{
    String date ="52/29/2500";
    Date dateFromString = DateHelper.getDateFromString(date, DateHelper.DD_MM_YYYY_FORMAT);

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateHelper.DD_MM_YYYY_FORMAT);
    Date dateWithSimpleFormat = simpleDateFormat.parse(date);

    Assert.assertNotNull(dateFromString);
    Assert.assertNotNull(dateWithSimpleFormat);

    Assert.assertTrue(dateFromString.equals(dateWithSimpleFormat));

    System.out.println("dateFromString" + dateFromString);
    System.out.println("dateWithSimpleFormat" + dateWithSimpleFormat);
}

输出是:

1
2
dateFromString Wed Jun 21 00:00:00 CEST 2502
dateWithSimpleFormat Wed Jun 21 00:00:00 CEST 2502

DateHelper.DD_MM_YYYY_FORMAT 模式是 dd/MM/yyyygetDateFromString 是一种使用 commons-lang 库将字符串日期解析为 Date 对象的方法。

为什么要使用 java.util.Date 对象来验证日期的有效性?


您需要设置 simpleDateFormat.setLenient(false); 以使 SimpleDateFormat 严格验证您的输入。

您可以参考 setLenient 文档以进一步了解。根据定义,

1
2
3
Specify whether or not date/time parsing is to be lenient. With lenient parsing,
the parser may use heuristics to interpret inputs that do not precisely match this
object's format. With strict parsing, inputs must match this object's format.

java.time

1
2
3
4
5
6
7
8
9
10
    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");

    String date ="52/29/2500";
    try {
        LocalDate dateWithJavaTime = LocalDate.parse(date, dateFormatter);

        System.out.println("dateWithJavaTime" + dateWithJavaTime);
    } catch (DateTimeParseException dtpe) {
        System.out.println("Invalid date." + dtpe);
    }

这段代码的输出是:

Invalid date. java.time.format.DateTimeParseException: Text
'52/29/2500' could not be parsed: Invalid value for MonthOfYear (valid
values 1 - 12): 29

请享受不仅验证有效,而且错误消息的精确度。

其他结果:

  • 对于字符串 52/11/2500,结果是一个€?无效的日期。 java.time.format.DateTimeParseException:无法解析文本 \\'52/11/2500\\':DayOfMonth 的值无效(有效值 1 - 28/31):52a€?。
  • 对于字符串 29/02/2019,我们得到一个€?dateWithJavaTime 2019-02-28a€?,这可能令人惊讶。要拒绝此字符串,请使用

    1
    2
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu")
                .withResolverStyle(ResolverStyle.STRICT);

    现在我们得到

    Invalid date. java.time.format.DateTimeParseException: Text
    '29/02/2019' could not be parsed: Invalid date 'February 29' as '2019'
    is not a leap year

    再次享受信息的精确性。


使用 simpleDateFormat.setLenient(false); 启用严格解析。