Java 10 个 DateTimeFormatter 模式符号用于 "E" 和 "MMM" 添加句点

Java 10 DateTimeFormatter pattern symbols for "E" and "MMM" adding periods

所以在 Java 8 以下:

DateTimeFormatter df = DateTimeFormatter.ofPattern("E d MMM yyyy");

以这种方式应用时:

LocalDate date = LocalDate.now();
date.format(df);

会产生这样的结果:

"Available on Thu 30 Aug 2018"

然而,当 Java 10 中的 运行 时,完全相同的代码会产生以下内容:

"Available on Thu. 30 Aug. 2018"

注意日和月部分之后的句点...

我很清楚我可以只替换字符串中的句点,但我真的不想这样做。我想知道为什么会发生这种变化,是否有替代模式?

我在网上找不到任何关于此更改的参考资料。

编辑:

根据下面 Basil 的回答,这不是 Java 版本问题。这是一个区域设置问题。带有我的代码的 docker 图像在美国语言环境中是 运行ning,而我的机器在澳大利亚语言环境中是 :)

验证Locale

标点符号和相关事项(缩写、拼写、元素顺序)被定义为文化规范的一部分。在 Java 中,这些文化规范由 Locale.

指定

语言环境在 运行 时间

发生变化

一个可能的问题是您在未明确指定 Locale 的情况下 运行ning 代码,这意味着您隐含地依赖于 JVM 当前的默认语言环境。该默认值可能因 运行 时间环境而异。

记录您的默认语言环境,以进行验证。

Locale.getDefault().toString()

研究下面的代码示例,了解如何明确指定您的 Locale。我建议 always 让你的 Locale 明确(顺便说一下,时区也是如此)。

运行时间

定义有所不同

请注意,Java9 的日期时间本地化发生了重大变化:JEP 252: Use CLDR Locale Data by Default. At least for OpenJDK-based JVMs, the source of information about these cultural norms switched to the Common Locale Data Repository provided by the Unicode Consortium

对于这里讨论的特殊情况,当使用 Locale.US 时,我们看不出有什么区别,您可以在下面的代码示例中看到。但是对于某些语言环境,您可能确实会看到 Java 8 及更早版本与 Java 9 及更高版本之间的差异。

所以,我再次想知道您的问题的第二个示例是否涉及不同的语言环境。修复方法是明确指定您或您的用户期望的语言环境,而不是隐式依赖 JVM 当前的瞬时默认值(默认值可以随时更改 during运行time !).

无法确认问题

System.out.println( System.getProperty( "java.version" ) );
System.out.println( Locale.getDefault().toString() );

LocalDate ld = LocalDate.of( 2018 , Month.AUGUST , 30 );

Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E d MMM yyyy" , locale );
String output = ld.format( f );

System.out.println( output );

当 运行 在 Java 10.0.2 中通过 IntelliJ 2018.3 中基于 OpenJDK 的 Zulu JVM by Azul Systems 在 macOS High Sierra 下的 MacBook Pro Retina 上,我得到:

10.0.2

en_US

Thu 30 Aug 2018

对于Java 8,请参见code run live at IdeOne.com。请注意,IdeOne.com 中使用的 JVM 仅固定为单个区域设置,Locale.US

en_US

1.8.0_112

output: Thu 30 Aug 2018

澳大利亚

这是一个示例,说明您的输出在其他一些英语地区(例如澳大利亚)如何成为常态。

LocalDate ld = LocalDate.of( 2018 , Month.AUGUST , 30 );

Locale locale = new Locale( "en" , "AU" );  // "en-AU" is English Australia.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E d MMM yyyy" , locale );
String output = ld.format( f );

Thu. 30 Aug. 2018