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

Jes*_*ang 9 date-format date-parsing java-8 java-time

使用Java 8,下面的代码将"18"解析为年"0018"而不是"2018".

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/y");
return LocalDate.parse(date, formatter);
Run Code Online (Sandbox Code Playgroud)

输入日期为"01/05/18".

1)为什么结果是"0018"?难道DateTimeFormatter没有按照80-20规则?

2)如何控制SimpleDateFormat解析为19xx或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位数年份的例外情况.

Ole*_*.V. 16

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

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

试试吧:

    System.out.println(parseDateString("01/05/18"));
    System.out.println(parseDateString("01/06/2018"));
Run Code Online (Sandbox Code Playgroud)

这印刷:

2018-01-05
2018-01-06
Run Code Online (Sandbox Code Playgroud)

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

如果您想要更精确地控制如何解释两位数年份:

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

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

    System.out.println(parseDateString("01/05/22"));
Run Code Online (Sandbox Code Playgroud)

这打印:

1922-01-05
Run Code Online (Sandbox Code Playgroud)

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

  • 这是我正在寻找的解决方案,特别是`appendValueReduced(ChronoField.YEAR,2,2,1920)`方法.`appendValueReduced(ChronoField.YEAR,2,2,LocalDate.now().minusYears(80))`可用于实现我在问题中提到的80-20规则的行为(使用`SimpleDateFormat.set2DigitYearStart(Date) `). (2认同)