Java 分区日期更改行为jdk 8/11

Java 分区日期更改行为jdk 8/11,java,java-8,java-11,zoneddatetime,java-12,Java,Java 8,Java 11,Zoneddatetime,Java 12,我正在将一个应用程序从jdk 8迁移到11,我可以看到ZoneDateTime的变化是关于夏令时的行为。 JDK8 输出: 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:1

我正在将一个应用程序从jdk 8迁移到11,我可以看到ZoneDateTime的变化是关于夏令时的行为。 JDK8

输出: 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 我相信您在Java8中遇到的实际问题是以下错误:。bug的标题并不能说明整个故事。真正的问题是,在Java 8中,如果解析的字符串中包含时区ID,则ISO_ZONED_DATE_TIME(由您使用的一个参数ZonedDateTime.parse隐式使用)会忽略偏移量。这与2037年10月在巴黎使用的偏移量与字符串不一致的时区数据库相结合,会导致分析与字符串中偏移量冲突的时间点

这个错误在Java9中得到了修复。所以在Java9、10和11中,由于关于偏移量的相同分歧仍然存在,所以解析的时刻基于字符串的偏移量。然后使用时区数据库中的规则将其从字符串转换为时区。这将导致偏移量从+01:00更改为+02:00,并且一天中的小时数相应地从19:15更改为20:15。我同意Java9+的观点,这是正确的行为

不要将ZoneDateTime用于遥远的未来日期 您的问题也部分是由于使用
ZoneDateTime
作为未来日期造成的。这只建议在不久的将来使用,我们假设不会更改分区规则。对于2037年的日期和时间,如果您知道时间的瞬间,则应使用
即时
,如果您只知道一天中的日期和时间,则应使用
本地日期时间
。只有当时间临近并且您相信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行为,正如我所提到的,不建议您在此处使用
ZoneDateTime

    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[欧洲/巴黎]


使用OpenJDK 11.0.3,我得到了
2037-05-10T20:15+02:00[欧洲/巴黎]
很抱歉,我把我的代码片段弄错了。因此,使用Jdk11/12确实会因为夏季夏令时而增加一个小时。jdk 8上的日期时间是2037-05-10T19:15:00,看来欧盟可能会在2021年放弃夏季时间(DST)。你知道2037年10月巴黎的偏移量是+01:00还是+02:00吗?我的怀疑是它还没有决定。在您使用的两个版本之间,基础时区数据库已经更改。按照以下步骤查看您正在使用的数据库版本,然后搜索以查看这些版本之间的更改。
    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);