gpt4 book ai didi

java - 100 年前的 ZonedDateTime 和 LocalDateTime 是不同的

转载 作者:行者123 更新时间:2023-12-01 09:52:48 33 4
gpt4 key购买 nike

我看到的行为非常奇怪 - 有时 LocalDateTime 会等于 ZonedDateTime,其他时候会相差 1 小时或 2 小时,有时会相差 30 分钟。所有这些奇怪的差异都取决于我减去的年份。有人可以解释发生了什么事吗?尝试过jdk1.8.0_65jdk1.8.0_91MacOS 10.11.5。我与 UTC 合作:

ZoneOffset offset = ZoneOffset.UTC;

这里有一些实验。对于 1919 个值可能会存在纳秒或毫秒的差异,这是预期的:

assertEquals(                     
LocalDateTime.now(offset).minusYears(85).toInstant(offset),
ZonedDateTime.now().minusYears(85).withZoneSameInstant(offset).toInstant());

1919 年相差 1 小时:

assertEquals(                 
LocalDateTime.now(offset).minusYears(86).toInstant(offset),
ZonedDateTime.now().minusYears(86).withZoneSameInstant(offset).toInstant());

Expected :<1930-05-28T20:19:10.383Z>
Actual :<1930-05-28T21:19:10.383Z>

1920 年相差 2 小时:

assertEquals(                    
LocalDateTime.now(offset).minusYears(95).toInstant(offset),
ZonedDateTime.now().minusYears(95).withZoneSameInstant(offset).toInstant());

Expected :<1921-05-28T20:21:45.094Z>
Actual :<1921-05-28T18:21:45.094Z>

对于 1921 年再次出现毫秒或纳秒差异:

assertEquals(                      
LocalDateTime.now(offset).minusYears(96).toInstant(offset),
ZonedDateTime.now().minusYears(96).withZoneSameInstant(offset).toInstant());

最奇怪的是 1930 年,相差 30 分钟:

assertEquals(                      
LocalDateTime.now(offset).minusYears(97).toInstant(offset),
ZonedDateTime.now().minusYears(97).withZoneSameInstant(offset).toInstant());

Expected :<1919-05-28T20:24:27.345Z>
Actual :<1919-05-28T19:53:08.346Z>

更新

正如 @Tunaki 指出的那样,我必须指定 ZonedDateTime 的偏移量:

assertEquals(                   
LocalDateTime.now(offset).minusYears(95).toInstant(offset),
ZonedDateTime.now(offset).minusYears(95).withZoneSameInstant(offset).toInstant());

最佳答案

问题是它不知道时区:LocalDateTime.now(offset).minusYears(97).toInstant(offset)。仅存在偏移。但这知道时区:ZonedDateTime.now().minusYears(97).toInstant()

  • ZoneId 包含有关地点和该地点的时差的信息。它知道 N 年前在那个特定时区,偏移量是 2 小时,而不是现在的 3 小时。
  • ZoneOffset 仅跟踪小时/分钟的变化。它不知道特定国家的时间变化历史。它只是“增加了时间”。

建议的(有点不正确)解决方案是让 ZonedDateTime 忘记区域并使用偏移量:ZonedDateTime.now(offset).minusYears(97)。现在,这将与具有相同偏移量的 LocalDateTime 一致 - 两者都会显示相同的不正确信息。但他们会同意,因为两者“只是增加几个小时”,而不是了解该地点历史上那个时间点的时差:

ZoneOffset offset = ZoneId.of("Europe/Moscow").getRules().getOffset(Instant.now());
assertEquals(
LocalDateTime.now(offset).minusYears(97).toInstant(offset),
ZonedDateTime.now(offset).minusYears(97).toInstant());

或者,我们可以设置 LocalDateTime 以显示该地点该时间的正确值:

ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Europe/Moscow")).minusYears(97);
ZoneOffset offset = zoned.getOffset();//agrees with history
assertEquals(
LocalDateTime.now().minusYears(97).toInstant(offset),
zoned.toInstant());

PS:这一切都表明 ZonedDateTime 在不同情况下可以以不同的方式工作 - 有时它知道时区,其他时候它只是“添加小时”,就像通过手动设置偏移量来使用 LocalDateTime 一样。对我来说这是一个奇怪的实现。 JodaTime 可能仍然是最好的 Java 实现。至少不用学几天就能理解。

关于java - 100 年前的 ZonedDateTime 和 LocalDateTime 是不同的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37503486/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com