Java 8 DateTimeFormatter 两位数年份 18 解析为 0018 而不是 2018?

Java 8 DateTimeFormatter two digit year 18 parsed to 0018 instead of 2018?

对于 Java 8,下面的代码将“18”解析为年份“0018”而不是“2018”。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/y");
return LocalDate.parse(date, formatter);

输入日期是“01/05/18”。

1) 为什么结果是“0018”? DateTimeFormatter 不遵循 80-20 规则吗?

2)How to control SimpleDateFormat parse to 19xx or 20xx?讲到SimpleDateFormat.set2DigitYearStart(Date)可以用来固定年份。 DateTimeFormatter有没有类似的东西?

我希望 "M/d/y" 能够解析 2 位和 4 位年份。

"M/d/yy" 抛出 4 位数年份的异常并将“01/05/97”解析为“2097-01-05”。理想情况下,这应该被解析为“1997-01-05”。

"M/d/yyyy" 抛出 2 位数年份的异常。

将格式化程序字符串更改为 "M/d/yy"

没有一个 yu 字符串可以让您同时解析两位数和四位数字的年份。但是,您可以使用格式模式字符串中的可选部分来指定可能存在两位数或四位数字的年份:

public static LocalDate parseDateString(CharSequence date) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/[uuuu][uu]");
    return LocalDate.parse(date, formatter);
}

试一试:

    System.out.println(parseDateString("01/05/18"));
    System.out.println(parseDateString("01/06/2018"));

这打印了:

2018-01-05
2018-01-06

在格式模式字符串中,您需要将四位数年份放在首位。使用相反的顺序,当尝试解析四位数年份时,格式化程序将解析两位数,并确定到目前为止它是成功的,然后抱怨两位数后未解析的文本。

如果您想更精确地控制两位数年份的解释方式:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("M/d/")
            .optionalStart()
            .appendPattern("uuuu")
            .optionalEnd()
            .optionalStart()
            .appendValueReduced(ChronoField.YEAR, 2, 2, 1920)
            .optionalEnd()
            .toFormatter();

在上面的方法中使用这个格式化程序让我们试试:

    System.out.println(parseDateString("01/05/22"));

这会打印:

1922-01-05

以 1920 为基数(如我的示例代码中所示)将导致两位数年份在 1920 到 2019 的间隔内结束。根据您的要求调整值。