YYYY-ww 的 DateTimeFormatter 在 mac 和 ubuntu 上的解析不同
DateTimeFormatter of YYYY-ww resolves differently on mac and ubuntu
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"))
);
为什么这个模式 YYYY-ww
在 Ubuntu 和 Mac 上的解析不同:
Ubuntu:(默认语言环境 en_US,我的电脑)
2022-20
2022-21
Mac:(默认语言环境 en_GB)
2022-19
2022-20
编辑
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"))
);
returns:
2022-19
2022-20
不过,问题是为什么模式 ww
是 Locale 特定的?我在 https://docs.oracle.com/javase/8/docs/api/java/time/temporal/WeekFields.html 的文档中没有看到这一点
或 https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
在美国,一年的第一周可以有 1 到 7 天,而在英国,一年的第一周至少需要 4 天。
WeekFields.of(Locale.UK).getMinimalDaysInFirstWeek() // 4
WeekFields.of(Locale.US).getMinimalDaysInFirstWeek() // 1
此外,美国的一周从周日开始,而英国的一周从周一开始。
这意味着对于美国来说,2022 年的第一周是 2022-01-01 的单个星期六,2022-01-02 是第二周的开始。另一方面,对于英国,2022 年的第一周从 2022-01-03 开始,因为一年的前两天不构成一周。这就是美国机器额外一周的来源。
使用 ofPattern
创建 DateTimeFormatter
时,使用机器的默认格式化语言环境:
The formatter will use the default FORMAT locale. This can be changed using withLocale(Locale)
on the returned formatter
因此有所不同。
我猜你想在此处使用标准 ISO 8601 weeks,而不想与语言环境有任何关系。一种方法是使用 IsoFields
:
构造一个 DateTimeFormatter
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"))
);
“周”的定义因地区而异
是正确的。一周有多种定义,它们因地区而异。
您问的是:
Still, the question is why pattern ww is Locale specific?
因为周的定义是文化。
即使将我们的范围限制在西方目前常见的 seven-day 周,这七天中的哪一天是一周的第一天?星期一在欧洲很常见,而美国则使用星期日。第一周应该从一周的第一天的第一次出现开始吗?或者一周应该从 1 月 1 日开始?
ISO 8601 标准
如果您想要一致性,请考虑使用标准 ISO 8601 周定义:
- 星期一是一周的第一天,星期天是最后一天。
- 第 1 周包含日历年的第一个星期四。
- week-based 年有 52 或 53 个完整的 7 天周。
- 第一周和最后一周可能分别是 previous/next 日历年的零天或多天。
标准格式是 four-digit 年、连字符、一个 W
和两位数的周数。标准格式经过巧妙设计,可以避免歧义,易于机器解析,并且可以被不同文化背景的人理解。
要使用 ISO 8601 周,我建议添加 ThreeTen-Extra library to your project for its YearWeek
class。
YearWeek yw = YearWeek.parse( "2022-W19" ) ;
String output = yw.toString() ;
按日期获取 year-week。
LocalDate ld = LocalDate.parse( "2022-05-10" ) ;
YearWeek yw = YearWeek.from( ld ) ;
从以标准 ISO 8601 格式的文本表示的 UTC 时刻获取 year-week。下面看到的末尾的 Z
表示与 UTC 的偏移量为零 hours-minutes-seconds,发音为“Zulu”。
String input = "2022-05-10T00:00:00.00Z" ;
Instant instant = Instant.parse( input ) ;
OffsetDateTime odt = instant.at( ZoneOffset.UTC ) ;
YearWeek yw = YearWeek.from( odt ) ;
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"))
);
为什么这个模式 YYYY-ww
在 Ubuntu 和 Mac 上的解析不同:
Ubuntu:(默认语言环境 en_US,我的电脑)
2022-20
2022-21
Mac:(默认语言环境 en_GB)
2022-19
2022-20
编辑
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"))
);
returns:
2022-19
2022-20
不过,问题是为什么模式 ww
是 Locale 特定的?我在 https://docs.oracle.com/javase/8/docs/api/java/time/temporal/WeekFields.html 的文档中没有看到这一点
或 https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
在美国,一年的第一周可以有 1 到 7 天,而在英国,一年的第一周至少需要 4 天。
WeekFields.of(Locale.UK).getMinimalDaysInFirstWeek() // 4
WeekFields.of(Locale.US).getMinimalDaysInFirstWeek() // 1
此外,美国的一周从周日开始,而英国的一周从周一开始。
这意味着对于美国来说,2022 年的第一周是 2022-01-01 的单个星期六,2022-01-02 是第二周的开始。另一方面,对于英国,2022 年的第一周从 2022-01-03 开始,因为一年的前两天不构成一周。这就是美国机器额外一周的来源。
使用 ofPattern
创建 DateTimeFormatter
时,使用机器的默认格式化语言环境:
The formatter will use the default FORMAT locale. This can be changed using
withLocale(Locale)
on the returned formatter
因此有所不同。
我猜你想在此处使用标准 ISO 8601 weeks,而不想与语言环境有任何关系。一种方法是使用 IsoFields
:
DateTimeFormatter
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"))
);
“周”的定义因地区而异
您问的是:
Still, the question is why pattern ww is Locale specific?
因为周的定义是文化。
即使将我们的范围限制在西方目前常见的 seven-day 周,这七天中的哪一天是一周的第一天?星期一在欧洲很常见,而美国则使用星期日。第一周应该从一周的第一天的第一次出现开始吗?或者一周应该从 1 月 1 日开始?
ISO 8601 标准
如果您想要一致性,请考虑使用标准 ISO 8601 周定义:
- 星期一是一周的第一天,星期天是最后一天。
- 第 1 周包含日历年的第一个星期四。
- week-based 年有 52 或 53 个完整的 7 天周。
- 第一周和最后一周可能分别是 previous/next 日历年的零天或多天。
标准格式是 four-digit 年、连字符、一个 W
和两位数的周数。标准格式经过巧妙设计,可以避免歧义,易于机器解析,并且可以被不同文化背景的人理解。
要使用 ISO 8601 周,我建议添加 ThreeTen-Extra library to your project for its YearWeek
class。
YearWeek yw = YearWeek.parse( "2022-W19" ) ;
String output = yw.toString() ;
按日期获取 year-week。
LocalDate ld = LocalDate.parse( "2022-05-10" ) ;
YearWeek yw = YearWeek.from( ld ) ;
从以标准 ISO 8601 格式的文本表示的 UTC 时刻获取 year-week。下面看到的末尾的 Z
表示与 UTC 的偏移量为零 hours-minutes-seconds,发音为“Zulu”。
String input = "2022-05-10T00:00:00.00Z" ;
Instant instant = Instant.parse( input ) ;
OffsetDateTime odt = instant.at( ZoneOffset.UTC ) ;
YearWeek yw = YearWeek.from( odt ) ;