Java 8+ 中的 DateTimeFormatter.ISO_LOCAL_DATE 与 DateTimeFormatter.ofPattern("yyyy-MM-dd")
Posted
技术标签:
【中文标题】Java 8+ 中的 DateTimeFormatter.ISO_LOCAL_DATE 与 DateTimeFormatter.ofPattern("yyyy-MM-dd")【英文标题】:DateTimeFormatter.ISO_LOCAL_DATE vs DateTimeFormatter.ofPattern("yyyy-MM-dd") in Java 8+ 【发布时间】:2018-05-21 17:40:42 【问题描述】:我有一个使用ZonedDateTime.now(ZoneOffset.of("+2:00")).minusDays(5)
创建的日期。现在我想将其格式化为yyyy-MM-dd
。
在 Java 8+ 中,DateTimeFormatter.ISO_LOCAL_DATE
是否等同于 DateTimeFormatter.ofPattern("yyyy-MM-dd")
?
输出看起来相同,并且从文档看来,它们应该是相同的。然而,其中的“本地”部分让我停下来。注意我有一个偏移量,我正在使用 ZonedDateTime。我想确保没有任何陷阱或“它们是相同的,除非在这些特殊情况下,因为您正在处理偏移等”。
【问题讨论】:
你不能检查the sources或做一些测试吗? 第一个 Google 结果:docs.oracle.com/javase/8/docs/api/java/time/format/… 我确实阅读了文档并进行了测试。输出看起来相同,并且从文档中看起来它们应该是相同的。然而,其中的“本地”部分让我停下来。注意我有一个偏移量,我正在使用 ZonedDateTime。我想我更多的是寻找任何陷阱或“它们是相同的,除非在这些特殊情况下,因为你正在处理偏移等” "local" 表示在进行日期时间工作时“没有时区,没有从 UTC 偏移”。 【参考方案1】:对于表示 5 天前的日期时间格式化,这两个格式化程序是等效的。它们不会对所有可能的日期都等价,无论是格式化还是解析。
让我们尝试一下:
DateTimeFormatter yyyyMmDd = DateTimeFormatter.ofPattern("yyyy-MM-dd");
int[] yearsToTest = -900_000_000, -10_000, -2, 0, 1, 2017, 2099, 9999, 10_000, 900_000_000 ;
for (int year : yearsToTest)
LocalDate date = LocalDate.of(year, Month.DECEMBER, 2);
String dateFormattedIso = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
String dateFormattedYyyyMmDd = date.format(yyyyMmDd);
String diff = dateFormattedIso.equals(dateFormattedYyyyMmDd) ? "Same" : "Different";
System.out.format("%-18s%-18s%s%n", dateFormattedIso, dateFormattedYyyyMmDd, diff);
上面的sn-p打印:
-900000000-12-02 +900000001-12-02 Different
-10000-12-02 +10001-12-02 Different
-0002-12-02 0003-12-02 Different
0000-12-02 0001-12-02 Different
0001-12-02 0001-12-02 Same
2017-12-02 2017-12-02 Same
2099-12-02 2099-12-02 Same
9999-12-02 9999-12-02 Same
+10000-12-02 +10000-12-02 Same
+900000000-12-02 +900000000-12-02 Same
因此,对于格式化而言,它们似乎在共同时代 (“AD”) 的几年中是等价的,但在共同时代之前的几年里却不是。 yyyy
尊重没有0年,所以LocalDate
中的0年被渲染为1年。据了解是BCE,不打印这个信息。 ISO 格式化程序按字面意思表示年份,带有符号和所有内容。
您可以通过使用uuuu
而不是yyyy
来获得ISO_LOCAL_DATE
的行为。
这里的“本地”仅表示没有时区,反过来意味着您的ZonedDateTime
中的时区信息不会被打印出来,这是您无论如何都不会想到的。
【讨论】:
另一个区别可能是宽松的行为。据我所知,常量格式化程序是严格的,而基于模式的格式化程序在解析方面很聪明。这可能与“2017-02-29”之类的表达式有关(在严格模式下被拒绝并在智能模式下调整)。 是的,@MenoHochschild,我没有考虑解析中的差异,肯定有一些。感谢您在这个方向上的贡献。【参考方案2】:这里的 ISO 表示ISO-8601。该格式目前是并且可能永久是 yyyy-MM-dd (没有时区,因为它是本地的)。但是问问你自己 - 你想要 ISO 格式,还是想要 yyyy-MM-dd?它们相同的事实对您来说应该是微不足道的 - 您正在根据想要标准表示或想要特定表示做出决定。或者问题可能是“我不确定我是否想要 ISO 格式的日期……是吗?” - 答案是,在所有条件相同的情况下,您可能会这样做。
【讨论】:
以上是关于Java 8+ 中的 DateTimeFormatter.ISO_LOCAL_DATE 与 DateTimeFormatter.ofPattern("yyyy-MM-dd")的主要内容,如果未能解决你的问题,请参考以下文章
如何仅使用@DateTimeFormat 将日期@ConfigurationProperties 与时间绑定?
ResolverStyle.STRICT 在 `@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)` 中不起作用