ZonedDateTime更改行为jdk 8/11 [英] ZonedDateTime change behavior jdk 8/11

查看:259
本文介绍了ZonedDateTime更改行为jdk 8/11的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am migrating an application from jdk 8 to 11 and I can see ZonedDateTime change is behavior about daylight saving time. 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 [欧洲/巴黎]

output: 2037-05-10T19:15+02:00[Europe/Paris]

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

2037-05-10T20:15+02:00[Europe/Paris]

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

Can someone explain to me why did they change this behavior ?

最诚挚的问候,

推荐答案

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

我相信您在Java 8中遇到的实际上是这个错误: ZonedDateTime. parse()在DST下降过渡周围返回错误的ZoneOffset .错误标题并不能说明全部情况.真正的问题是,在Java 8 DateTimeFormatter.ISO_ZONED_DATE_TIME(您所使用的一个参数ZonedDateTime.parse隐式使用)中,如果在解析的字符串中包含时区ID,则会忽略偏移量.结合使用时区数据库,该数据库与您的字符串关于2037年10月巴黎使用的偏移量不符,将导致解析时间与字符串中的偏移量相冲突.

It’s a known bug in Java 8: JDK-8066982

I believe that what you are experiencing in Java 8 is really this bug: ZonedDateTime.parse() returns wrong ZoneOffset around DST fall transition. The bug title doesn’t tell the whole story. The real issue is that in Java 8 DateTimeFormatter.ISO_ZONED_DATE_TIME (which is implicitly used by the one-arg ZonedDateTime.parse that you use) ignores the offset if a time zone ID is included in the parsed string. This in combination with a time zone database that disagrees with your string about the offset used in Paris in October 2037 causes a moment in time to be parsed that conflicts with the offset in the string.

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

The bug is fixed in Java 9. So in Java 9, 10 and 11, since the same disagreement about offset is still there, the moment parsed is based on the offset of the string. It is then converted to the time zone from the string using the rules from the time zone database. This causes the offset to be changed from +01:00 to +02:00 and the hour of day correspondingly from 19:15 to 20:15. I agree with Java 9+ that this is the correct behaviour.

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

Your problem is also partly caused by using ZonedDateTime for a future date. This is only recommended for the very near future where we assume that no zone rules are changed. For a date and time in 2037, you should either use an Instant if you know the moment in time, or a LocalDateTime if you know just the date and time of day. Only when the time draws near and you trust that your Java installation has got the last time zone updates, convert to a ZonedDateTime.

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

As has been discussed in the comments, we probably don’t know the correct UTC offset for Paris in October 2037 yet. It seems that EU is likely to abandon summer time (DST) from 2021, and as far as I know, the French politicians have not yet decided what the time will be in France after that.

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

To get the time from the string (19:15), parse into a 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上运行):

Output is (run on Java 11):

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

Date and time from string: 2037-05-10T19:15

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

In case you wanted the full Java 8 behaviour on a later Java version — as I mentioned, it’s not recommended, you shouldn’t use ZonedDateTime here:

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

Time from string in zone from string: 2037-05-10T19:15+02:00[Europe/Paris]

这篇关于ZonedDateTime更改行为jdk 8/11的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆