DateTimeFormatter是否与操作系统相关?

3
以下代码:
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);

根据操作系统的不同,结果也会有所不同:

操作系统 格式 Java版本
Windows 2021年11月19日 下午2:13:12 1.8.0_312
macOS 2021年11月19日 下午2:13:12 1.8.0_312
Linux/Ubuntu 2021年11月19日 下午2:13:12 1.8.0_292

这是否是预期的结果?我的单元测试在不同的环境下失败,对我来说似乎很意外。


1
我看不出测试实际上使用了创建的 Locale locale = new java.util.Locale("en", "AU");。你是不是想写成 .withLocale(locale); 而不是 .withLocale(context.getLocale()); - Turing85
FormatStyle.SHORT 也有所不同:Windows 和 OSX 的格式为 19/11/21, 2:13 pm,而 Linux 的格式为 19/11/21 2:13 PM - Grahame Grieve
很好的问题。 Mac = Java版本:1.8.0_312,供应商:Temurin,语言环境为'en-US'。 Linux = Java版本:1.8.0_292,供应商:AdoptOpenJDK,语言环境为'en'。 Windows = Java版本:1.8.0_312,供应商:Temurin,语言环境为'en-US'。 - Grahame Grieve
1
所以... Mac 和 Windows 产生了相同的结果,并且是来自相同供应商的相同版本,具有相同的语言环境。但是对于 Linux 平台不是这样。你能否尝试将 Linux 机器的语言环境设置为相同,将安装版本升级到相同的供应商版本? - Turing85
1
问题:我们(你和我们)如何确信你展示的代码实际上代表了正在运行的内容?在转录时,您已经犯了至少两个错误-一次是省略输出的时间部分,另一次是因为您没有使用Locale实例。我们怎么能确定您的真实测试是否与您展示的内容不同?最有可能的是,您在每台机器上使用了不同的Locale而没有意识到。 - Michael
显示剩余14条评论
1个回答

2

Java 8:不依赖于操作系统

自 Java 的早期版本以来,Java 运行时引擎已经内置了区域设置数据。从 Java 8 开始,Unicode 公共区域设置数据存储库(CLDR)的数据也包含在 Java 中,但默认情况下仍优先使用 Java 自己的数据。

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

  1. 区域设置。
  2. 区域设置数据提供者。Java 可以从四个来源获取其区域设置数据:JRE 自己的数据、CLDR、安装的服务提供者(即您自己)和主机操作系统。哪些被使用以及使用什么优先级由 java.locale.providers 系统属性控制。
  3. 所选提供程序的区域设置数据版本。
  4. 对于 HOST 区域设置数据提供程序,显然还要考虑操作系统。

Java 8 中,默认值是首先使用 JRE 自己的区域设置数据,其次是任何配置的服务提供者。在任何情况下都不使用主机操作系统。因此,不设置系统属性 java.locale.providers 相当于将其设置为 JRE,SPI。这又不会产生任何对操作系统的依赖。

Java 9 中,将默认值更改为等同于 CLDR,COMPAT,其中 COMPATJRE 的新名称。这又不会产生任何对操作系统的依赖。

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

假设您依赖于默认的区域设置数据提供程序 JRE 和 SPI,并且您没有添加自己的服务提供程序(SPI),则您的不同结果必须是由不同版本的 Java 区域设置数据引起的。因此,他们显然将 Java 1.8.0_292 的区域设置数据更新到了 1.8.0_312。

那么 Windows 和 Mac 运行相同的 1.8.0_312 版本,为什么会有微小的差异,即 Nov 后面的点呢?虽然我希望他们为不同操作系统的 Java 安装程序提供相同版本的区域设置数据,但我能想到的解释是,在这种情况下,他们可能没有这样做。

更多观察结果

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

Java 格式 操作系统 测试人员
1.8.0_121 2021年11月19日 下午2:13:12 MacOS
1.8.0_271 2021年11月19日 下午2:13:12 Windows
1.8.0_292 2021年11月19日 下午2:13:12 Ubuntu
1.8.0_312 2021年11月19日 下午2:13:12 Windows
1.8.0_312 2021年11月19日 下午2:13:12 MacOS
9.0.4 2021年11月19日 下午2:13:12 MacOS
15.0.1 2021年11月19日 下午2:13:12 Windows

最后一行的结果很有趣,您的结果也是。

链接


是的,至少大部分与版本相关。 - Grahame Grieve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接