Luk*_*s F 15 java jvm java-8 java-10 localdate
我这里有一个非常简单的程序:
public static void main(String[] args) {
LocalDate year = LocalDate.ofYearDay(2022, 100);
System.out.println(year);
System.out.println(WeekFields.of(Locale.GERMAN).weekOfYear());
System.out.println(year.with(WeekFields.of(Locale.GERMAN).weekOfYear(), 0));
System.out.println(year.with(WeekFields.of(Locale.GERMAN).weekOfYear(), 0).with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)));
}
Run Code Online (Sandbox Code Playgroud)
但是它在JVM 8和JVM 10上的行为有所不同。问题似乎出在的实现上WeekFields.of(Locale.GERMAN).weekOfYear()。
在JVM 10上,我得到以下结果:
JVM 10
2022-04-10
WeekOfYear[WeekFields[SUNDAY,1]]
2021-12-19
2021-12-13
Run Code Online (Sandbox Code Playgroud)
而在JVM 8上:
JVM 8
2022-04-10
WeekOfYear[WeekFields[MONDAY,4]]
2022-01-02
2021-12-27
Run Code Online (Sandbox Code Playgroud)
为什么会这样呢?我是否正在做某事,可能会导致不确定的行为?还是在某处指定了这种行为变化?
JVM10:
$ java -version
openjdk version "10.0.2" 2018-07-17
OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4)
OpenJDK 64-Bit Server VM (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4, mixed mode)
Run Code Online (Sandbox Code Playgroud)
JVM8
$ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-2ubuntu0.18.04.1-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
Run Code Online (Sandbox Code Playgroud)
编辑:
JVM 9具有相同的行为JVM 8并JVM 11表现为JVM 10
编辑2:我实际上在github上找到了改变了行为的提交-> 我很好奇为什么这被改变了。
Men*_*ild 11
这样的周字段是高度本地化的,因此取决于基础JVM的本地化资源,该资源可以从一个发行版更改为另一个发行版。
I think JVM10 is more correct because Locale.GERMAN does not refer to any country so Java simple assumes US (somehow questionable to handle this country as world standard, but so is Java).
You should better use Locale.GERMANY. That country indeed does use Monday as first day of week (in contrast to US starting on Sunday which is used as fallback for GERMAN which is just a language and not a country.
The current CLDR data list for the fallback country/territory "001" (= worldwide) the week definitions (Monday as first day of week and 1 = minimal days of first week in calendar year). Astonishingly, this is different from US-definition (Sunday, 1). I think, Oracle has just done its own thing. Personally, I agree with @Holger and rather expect ISO-8601 as fallback (Monday, 4).
However, you might be able to restore the Java-8-behaviour on your JVM-10-machine by setting following system property (not tested):
java.locale.providers=COMPAT,CLDR,SPI
Run Code Online (Sandbox Code Playgroud)
以下两个选项是等效的。选择您认为最适合您的情况的一种。
WeekFields.ISOWeekFields.of(Locale.GERMANY) 使用国家,德国,而不是语言,德语。这里有两个不同之处:
不同语言环境下周方案的定义是语言环境数据的一部分。Java 最多可以从四个来源获取其语言环境数据。从早期版本开始,Java 包含自己的语言环境数据,这些是 Java 8 之前的默认值。从 Java 8 CLDR(Unicode 通用语言环境数据存储库)数据也被包含在内,这些成为 Java 9 的默认值。这显然改变了一些正如您所经历的那样,功能并破坏了一些旧代码。更准确地说,默认值是:
可以通过设置系统属性来覆盖默认值java.locale.providers。因此,我们可以通过将此属性设置为 来获得 Java 9 及更高版本中的 Java 8 行为COMPAT,SPI。相反,我们可以通过将其设置为 来获得 Java 8 中的 Java 10 行为CLDR,JRE。因此,从根本上说,Java 版本之间的差异并不大,而只是它们的默认值之间的差异。
从 Java 到 CLDR 数据的变化是这样的:Java 语言环境数据根据语言的主要使用地将周定义分配给仅语言的语言环境(如德语)。相比之下,CLDR 的理念是您可以说世界上任何国家的任何语言,并且您宁愿根据国家而不是语言来选择周计划。因此,未指定国家/地区(如德语)的区域设置都使用全球默认的周定义。
为什么全球默认周定义在 CLDR 中是“Sunday, 1”我不明白。正如其他人一样,我会期望并更喜欢 ISO,即国际标准“星期一,4”。正如我在评论中所说,我还发现了一条注释,说应该是这种情况,但仍然不是(至少在 Java 8 到 11 中使用的 CLDR 版本中不是这样)。
正如您所观察到的,在具有默认语言环境数据的 Java 9 上,Locale.GERMAN
即使 CLDR 应该是第一个默认值,您也会从中获得“星期一 4” 。如果在另一方面,我设置java.locale.providers到CLDR独自一人,我得到“星期日1”在Java中10和11。
一个可能的解释是 Java 9 中使用的 CLDR 版本不包括德语的周定义。因此,对于默认提供程序 CLDR、COMPAT,Java 将使用 COMPAT,后者为德语提供“Monday, 4”。当我单独使用 CLDR 时,它会返回到全球基本默认值“星期日,1”。如果这个解释是正确的(我不能保证),Java 10 和 11 中使用的 CLDR 数据版本似乎确实包含德语的周定义。
LocaleServiceProvider有关区域设置数据提供程序和默认提供程序规范的信息的文档:
CLDR 链接:
| 归档时间: |
|
| 查看次数: |
276 次 |
| 最近记录: |