YYYY-ww 的 DateTimeFormatter 在 mac 和 ubuntu 上解析不同

Bye*_*Bye 2 java date datetime-format

System.out.println(
    DateTimeFormatter.ofPattern("YYYY-ww").withZone(ZoneOffset.UTC).format(Instant.parse("2022-05-10T00:00:00.00Z"))
);
System.out.println(
    DateTimeFormatter.ofPattern("YYYY-ww").withZone(ZoneOffset.UTC).format(Instant.parse("2022-05-17T00:00:00.00Z"))
);
Run Code Online (Sandbox Code Playgroud)

为什么此模式YYYY-ww在 Ubuntu 和 Mac 上的解析不同:

Ubuntu:(默认区域设置 en_US,我的电脑)

2022-20
2022-21
Run Code Online (Sandbox Code Playgroud)

Mac:(默认区域设置 en_GB)

2022-19
2022-20
Run Code Online (Sandbox Code Playgroud)

编辑

System.out.println(
    DateTimeFormatter.ofPattern("YYYY-ww").withLocale(Locale.UK).withZone(ZoneOffset.UTC).format(Instant.parse("2022-05-10T00:00:00.00Z"))
);
System.out.println(
    DateTimeFormatter.ofPattern("YYYY-ww").withLocale(Locale.UK).withZone(ZoneOffset.UTC).format(Instant.parse("2022-05-17T00:00:00.00Z"))
);
Run Code Online (Sandbox Code Playgroud)

返回:

2022-19
2022-20 
Run Code Online (Sandbox Code Playgroud)

不过,问题是为什么模式ww是特定于区域设置的?我在https://docs.oracle.com/javase/8/docs/api/java/time/temporal/WeekFields.htmlhttps://docs.oracle.com/javase/8的文档中没有看到这一点/docs/api/java/time/format/DateTimeFormatter.html

Swe*_*per 6

在美国,一年的第一周可以有 1 到 7 天,而在英国,一年的第一周需要至少 4 天。

WeekFields.of(Locale.UK).getMinimalDaysInFirstWeek() // 4
WeekFields.of(Locale.US).getMinimalDaysInFirstWeek() // 1
Run Code Online (Sandbox Code Playgroud)

此外,美国的一周从周日开始,而英国的一周从周一开始。

这意味着对于美国来说,2022 年的第一周是 2022-01-01 的单个星期六,2022-01-02 是第二周的开始。另一方面,对于英国来说,2022 年的第一周从 2022 年 1 月 3 日开始,因为一年的前两天并不构成一周。这就是美国机器额外一周的原因。

创建DateTimeFormatterusing时ofPattern,将使用机器的默认格式化区域设置:

格式化程序将使用默认的 FORMAT 区域设置。这可以使用withLocale(Locale)返回的格式化程序进行更改

因此存在差异。

我想您想要这里的标准ISO 8601 周,并且不希望与语言环境有任何关系。一种方法是构造一个DateTimeFormatterusing IsoFields

var dtf = new DateTimeFormatterBuilder()
  .  appendValue(IsoFields.WEEK_BASED_YEAR, 4)
    .appendLiteral('-')
    .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2)
    .toFormatter().withZone(ZoneOffset.UTC);
System.out.println(
    dtf.format(Instant.parse("2022-05-10T00:00:00.00Z"))
);
System.out.println(
    dtf.format(Instant.parse("2022-05-17T00:00:00.00Z"))
);
Run Code Online (Sandbox Code Playgroud)