java - ZonedDateTime更改行为jdk 8/11

标签 java java-8 java-11 zoneddatetime java-12

我正在将应用程序从jdk 8迁移到11,我可以看到ZonedDateTime更改是关于夏时制的行为。
JDK8

        ZonedDateTime parse = ZonedDateTime.parse("2037-05-10T19:15:00.000+01:00[Europe/Paris]");
        System.out.println(parse);


输出:
2037-05-10T19:15 + 02:00 [欧洲/巴黎]

JDK11 / 12

        ZonedDateTime parse = ZonedDateTime.parse("2037-05-10T19:15:00.000+01:00[Europe/Paris]");
        System.out.println(parse);


2037-05-10T20:15 + 02:00 [欧洲/巴黎]

有人可以向我解释为什么他们会改变这种行为吗?

最好的祝福,

最佳答案

这是Java 8中的一个已知错误:JDK-8066982

我相信您在Java 8中遇到的实际上是以下错误:ZonedDateTime.parse() returns wrong ZoneOffset around DST fall transition。错误标题并不能说明全部问题。真正的问题在于,如果解析的字符串中包含时区ID,则在Java 8 DateTimeFormatter.ISO_ZONED_DATE_TIME(由您使用的one-arg ZonedDateTime.parse隐式使用)中忽略了偏移量。结合时区数据库,该时区数据库与您的关于字符串在2037年10月巴黎使用的偏移量不一致的时区数据库,将导致与该字符串中的偏移量冲突的时间被解析。

该错误已在Java 9中修复。因此,在Java 9、10和11中,由于仍然存在有关offset的相同分歧,因此,分析时间基于字符串的offset。然后使用时区数据库中的规则将其从字符串转换为时区。这将使偏移量从+01:00更改为+02:00,并将一天中的时间从19:15更改为20:15。我同意Java 9+,这是正确的行为。

不要将ZonedDateTime用于将来的日期

您的问题也部分是由将来使用ZonedDateTime引起的。仅在不久的将来我们建议这样做,因为我们假设不会更改区域规则。对于2037年的日期和时间,如果您知道时间,则应该使用Instant,或者如果您仅知道日期和时间,则应使用LocalDateTime。仅当时间临近并且您相信Java安装已更新了最新的时区时,才转换为ZonedDateTime

正如评论中所讨论的那样,我们可能尚不知道2037年10月巴黎的正确UTC偏移量。欧盟似乎有可能从2021年开始放弃夏令时(DST),据我所知,法国政客尚未决定此后的法国时间。

如果我们想从字符串中获取一天中的时间怎么办?

要从字符串(19:15)中获取时间,请解析为LocalDateTime

    String zdtString = "2037-05-10T19:15:00.000+01:00[Europe/Paris]";
    LocalDateTime dateTime
            = LocalDateTime.parse(zdtString, DateTimeFormatter.ISO_ZONED_DATE_TIME);
    System.out.println("Date and time from string: " + dateTime);


输出为(在Java 11上运行):


字符串中的日期和时间:2037-05-10T19:15


如果您希望在更高的Java版本上获得完整的Java 8行为-如我所提到的,不建议这样做,则不应在此处使用ZonedDateTime

    TemporalAccessor parsed = DateTimeFormatter.ISO_ZONED_DATE_TIME.parse(zdtString);
    LocalDateTime dateTime = LocalDateTime.from(parsed);
    ZoneId zone = ZoneId.from(parsed);
    ZonedDateTime java8Zdt = dateTime.atZone(zone);
    System.out.println("Time from string in zone from string: " + java8Zdt);



字符串中的字符串所在的区域中的时间:2037-05-10T19:15 + 02:00 [欧洲/巴黎]

关于java - ZonedDateTime更改行为jdk 8/11,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56255020/

相关文章:

java - 使用 Java 8 lambda 将列表映射转换为不同的映射

java - 将字符串数组添加到ArrayList中

java - UTF 到 ASCII 的转换

java - Pattern.asPredicate 中的错误?

java - 使用 Collections.sort 后在 List 中添加了新的排序方法

java-time - Java 11 上的 DateTimeParseException 但适用于 Java 10

java - 升级到 TLSv1.3 时 SSLEngine 使用的变化

java - 如何关闭异步任务的进度对话框并避免 "is your activity running error?"

java - 将 org.threeten.bp.* 和 org.joda.time* 转换为相应的 java.time.* 类的最佳方法

java - 如何解决java.lang.NoClassDefFoundError : javax/xml/bind/JAXBException