DateTimeFormatter 是否依赖于操作系统?

Is DateTimeFormatter Operating System Dependent?

以下代码:

Locale locale = new java.util.Locale("en", "AU");
DateTimeFormatter fmt = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(locale);
ZonedDateTime zdt = ZonedDateTime.parse("2021-11-19T14:13:12Z");
return fmt.format(zdt);

根据操作系统给出不同的结果:

OS Format Java
Windows 19 Nov. 2021, 2:13:12 pm 1.8.0_312
macOS 19 Nov 2021, 2:13:12 pm 1.8.0_312
Linux/Ubuntu 19/11/2021, 2:13:12 PM 1.8.0_292

这是预期的吗?我的单元测试在不同的上下文中失败,这对我来说似乎很意外

Java 8:对操作系统没有预期的依赖性

Java 运行时引擎从 Java 的早期版本开始就内置了语言环境数据。来自Java Unicode Common Locale Data Repository, CLDR 的 8 个数据也包含在 Java 中,但默认 Java 自己的数据仍然是首选。

使用格式化程序格式化日期和时间的结果预计取决于三个或四个因素:

  1. 在语言环境中。
  2. 关于区域设置数据的提供者。 Java 最多可以从四个来源获取其区域设置数据:JRE 自己的数据、CLDR、已安装的服务提供商(可以说是你自己)和主机操作系统。 java.locale.providers 系统 属性.
  3. 控制哪些被使用以及优先级是多少
  4. 关于所选提供商的区域设置数据的版本。
  5. 对于 HOST 语言环境数据提供程序显然在操作系统上。

Java 8 中,默认使用 JRE 自己的语言环境数据作为第一优先级,其次是任何配置的服务提供者。无论如何都不是主机操作系统。所以不设置系统属性java.locale.providers等同于设置为JRE,SPI。这反过来又不会对操作系统产生任何依赖性。

Java 9 中,默认值已更改为等同于 CLDR,COMPAT,其中 COMPAT 是 [=16= 的新名称].这反过来仍然不会对操作系统产生任何依赖性。

为什么你观察到不同的结果?

假设你依赖默认的语言环境数据提供者,JRE和SPI,并且你没有添加自己的服务提供者(SPI),那么你的不同结果一定是Java的不同版本造成的的语言环境数据。所以显然他们将语言环境数据从 Java 1.8.0_292 更新为 1.8.0_312.

Windows和Mac的细微差别都是运行1.8.0_312,Nov后面的那个点呢?虽然我原以为他们会为不同的操作系统使用 Java 安装程序提供相同版本的语言环境数据,但我能想到的解释是在这种情况下他们可能没有。

更多观测结果

我也运行了一些你的代码。以下 table 包括你和我的观察。在所有运行中,我都将 java.locale.providers 设置为 JRE,SPI 以在 Java 9 及更高版本上获得 Java 8 行为。

Java Format OS Tester
1.8.0_121 19/11/2021, 2:13:12 PM MacOS Me
1.8.0_271 19/11/2021, 2:13:12 PM Windows Me
1.8.0_292 19/11/2021, 2:13:12 PM Ubuntu You
1.8.0_312 19 Nov. 2021, 2:13:12 pm Windows You
1.8.0_312 19 Nov 2021, 2:13:12 pm MacOS You
9.0.4 19 Nov 2021, 2:13:12 pm MacOS Me
15.0.1 19/11/2021 2:13:12 PM Windows Me

最后的结果很有趣,你带点的结果也很有趣。

链接