关于Java 8和Java 11之间的Instant.toEpochMilli不匹配的问题。

3
这是我的第一篇帖子,所以如果我没有遵守所有的规则和惯例,请原谅我。我在这段代码中遇到了一个问题,在Java 8和Java 11中返回的纪元时间毫秒数不同。
String strDate = "2022-07-18 17:52:23 America/New_York";
DateTimeFormatter frmt  = new DateTimeFormatterBuilder()
    .appendPattern("yyyy-MM-dd HH:mm:ss VV")
    .parseDefaulting(ChronoField.HOUR_OF_DAY,0)
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR,0)
    .parseDefaulting(ChronoField.SECOND_OF_MINUTE,0)
    .parseDefaulting(ChronoField.NANO_OF_SECOND,0)
    .parseDefaulting(ChronoField.OFFSET_SECONDS,0)
    .toFormatter();

TemporalAccessor temporal = frmt.parse(strDate);
System.out.println(Instant.from(temporal).toEpochMilli()); 

输出:

  • Java 8 - 1658181143000 是纽约的正确值
  • Java 11 - 1658166743000 错误。该值是UTC/GMT的值

在Java 8中产生了正确的结果1658181143000,这是New_York时区的纪元值。但在Java 11中给出了1658166743000,这是UTC时区的纪元表示。通过代码调试,我发现库没有在正确的位置设置偏移量。非常感谢您的帮助。

提前致谢

期望得到纽约的正确纪元值。


我认为你可能需要在Java 11中将时区/地区作为JDK参数进行传递。这可能与以下内容有关:Joda日期时间在Java 8与Java 11之间返回的结果差异很大 - Mr. Polywhirl
我认为你可能需要在Java 11中将时区/区域设置作为JDK参数传递。可能与此相关:Joda日期时间在Java 8和Java 11之间返回非常不同的结果 - Mr. Polywhirl
不要以“关于问题”的形式开头问题标题...总结你的实际问题。同时,不要添加废话,如你是新手之类的,也不要添加感谢词。 - Mark Rotteveel
不要以“关于问题”的形式开始问题标题,而是总结你的真实问题。也不要添加不必要的措辞,如你是新来的之类的话,也不要添加感谢之类的内容。 - Mark Rotteveel
不要以“关于问题”的形式开头问题标题,而是要总结你的实际问题。另外,不要加入多余的废话,比如说你是新来的,也不要加入感谢的话语。 - undefined
1个回答

3
我不知道这是否是一个“设计缺陷”,但似乎问题是由此引起的:
.parseDefaulting(ChronoField.OFFSET_SECONDS,0)

如果你省略这行代码,那么你的代码将能正常工作。你可能认为parseDefaulting(ChronoField.OFFSET_SECONDS,0)使得ZoneId是可选的。实际上并不是这样。它只是默认了偏移量,而偏移量是由OXxZ指定的。而VV则指定了时区ID,与偏移量是不同的。所以你所做的是解析了一个包含时区ID但不包含偏移量的字符串,因此它默认为0。

非常感谢您的及时回复。在这种情况下是有效的,但是在Java11中,还有其他在Java8中工作正常的日期格式,在Java11中却无法正常工作。看起来java.time包在Java11中的向后兼容性被故意或者意外地破坏了。 - Mathew Mani
非常感谢您的迅速回复。在这种情况下,这是有效的,但是在Java8中有效的其他日期格式在Java11中却无法工作。看起来Java11中java.time包的向后兼容性可能是故意或者意外地被破坏了。 - Mathew Mani
非常感谢您的迅速回复。在这种情况下,这是有效的,但是在Java8中有效的其他日期格式在Java11中却无法正常工作。看起来Java11中的java.time包的向后兼容性可能是故意或者意外地被破坏了。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接