您是对的:Joda-Time DateTimeFormatter(这是您从 DateTimeFormat.shortDate() 获得的类型)比 java.time DateTimeFormatter 解析更宽松。在英语/新西兰语言环境中 (en-NZ) shortDate 使用格式模式 d/MM/yy 并将 20/5/2016 和 20/5/16 解析为 2016-05-20。
坦率地说,我觉得将两位数和四位数的年份都解释为同一年很讨厌。当格式指定两位数年份时,我预计四位数字会成为更严格的输入验证的错误。当格式指定两位数时接受一位数的月份也很宽松,但可能没有那么危险,更符合我们的预期。
java.time 也使用格式模式d/MM/yy(在 jdk-11.0.3 上测试)。解析时接受一位或两位数的日期,但坚持两位数的月份和两位数的年份。
您可能会在 java.time 中获得 Joda-Time 行为,但它需要您自己指定格式模式:
Locale loc = Locale.forLanguageTag("en-NZ");
DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("d/M/[yyyy][yy]", loc);
System.out.println(LocalDate.parse("20/5/2016", dateFormatter));
System.out.println(LocalDate.parse("20/5/16", dateFormatter));
输出是:
2016-05-20
2016-05-20
如果您想要一个适用于其他语言环境的高级解决方案,我相信您可以编写一段代码,从DateTimeFormatterBuilder.getLocalizedDateTimePattern 获取格式模式并通过将dd 替换为d、@987654335 来修改它@ 和 M 以及任意数量的 y 和 [yyyy][yy]。然后将修改后的格式模式字符串传递给DateTimeFormatter.ofPattern。
编辑:很高兴你有工作要做。在您的评论中,您说您使用了:
Stream<String> shortFormPatterns = Stream.of(
"[d][dd]/[M][MM]",
"[d][dd]-[M][MM]",
"[d][dd].[M][MM]",
"[d][dd] [M][MM]",
"[d][dd]/[M][MM]/[yyyy][yy]",
"[d][dd]-[M][MM]-[yyyy][yy]",
"[d][dd].[M][MM].[yyyy][yy]",
"[d][dd] [M][MM] [yyyy][yy]");
- 它涵盖了比您的 Joda-Time 格式化程序更多的情况。也许这很好。具体来说,您的 Joda-Time 格式化程序坚持在数字之间使用斜线
/ 并拒绝连字符、点或空格。此外,我相信 Joda-Time 会反对将年份完全排除在外。
- 虽然您确实需要
[yyyy][yy],但您不需要[d][dd] 或[M][MM]。只需 d 和 M 就足够了,因为它们也接受两位数(例如,您的代码中发生的情况是 [d] 解析一位或两位数,因此无论如何都不会使用 [dd])。
- 如果您只喜欢一个格式模式字符串,我希望
d[/][-][.][ ]M[/][-][.][ ][yyyy][yy] 可以工作(除了省略年份的情况)(我没有测试过)。