与Java时间解析UTC混淆 [英] Confusion with Java Time parsing UTC

查看:230
本文介绍了与Java时间解析UTC混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Java时间中的时间处理感到困惑.我长期以来一直在以下假设下工作:如果将时间戳记指定为zulu时间,则java将考虑与本地时间有关的偏移量.

I am confused with time handling in java time. I so long worked under the assumption that if a timestamp is specified as a zulu time, java would take care of the offset with regards to local time.

进行说明.我目前在BST中,其偏移量为UTC +1.考虑到这一点,我希望这段祖鲁时间:

To illustrate. I am currently in BST which has an offset of UTC +1. With that in mind, I would expect this zulu time:

2016-09-12T13:15:17.309Z

成为

2016-09-12T14:15:17.309 

LocalDateTime解析后.这是因为我的默认系统时间设置为BST,并且上面的时间戳(祖鲁时间)指定它是UTC时间.

LocalDateTime after parsing it. This is because my default systemtime is set to BST and the above timestamp (zulu time) specifies that it is a UTC time.

相反,请考虑以下示例:

Instead however consider this sample:

        String ts = "2016-09-12T13:15:17.309Z";
        LocalDateTime parse = LocalDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME);
        System.out.println(parse);

这将打印:

2016-09-12T13:15:17.309

因此,时间戳(解析为LocalDateTime)不会被识别为UTC时间,而是直接被视为localtime. 所以我想,也许我需要将其解析为ZonedDateTime并将其专门转换为LocalDateTime以获得正确的本地时间.通过此测试:

So the timestamp, parsed as a LocalDateTime, is not recognised as UTC time and instead treated as localtime directly. So I thought, maybe I need to parse it as a ZonedDateTime and convert it to LocalDateTime specifically in order to get the correct local time. With this test:

        String ts = "2016-09-12T13:15:17.309Z";
        ZonedDateTime parse = ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME);
        System.out.println(parse);
        System.out.println(parse.toLocalDateTime());

我得到了输出:

2016-09-12T13:15:17.309Z
2016-09-12T13:15:17.309

两个日期的输出相同.

Same output for both dates.

正确解析我能找到的唯一方法是:

The only way to correctly parse this that I could find, is:

    String ts = "2016-09-12T13:15:17.309Z";
    Instant instant = Instant.parse(ts); // parses UTC
    LocalDateTime ofInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    System.out.println(instant);
    System.out.println(ofInstant);

此打印:

2016-09-12T13:15:17.309Z
2016-09-12T14:15:17.309

那是正确的.

所以问题是:

  • java时间不能识别UTC时间戳并将其解析为正确的系统默认值吗?
  • 如何使用LocalDateTime#parse方法获得正确的结果?
  • 我现在应该对所有内容使用Instant并放弃分析吗?
  • Shouldn't java time recognise a UTC timestamp and parse it to the correct system default?
  • How can I use the LocalDateTime#parse approach to get the correct result?
  • Should I use Instant for everything now and discard the parsing?

问题是jersey/jackson的java时间模块使用ISO格式和常规的LocalDateTime#parse方法解析时间戳.我意识到我的时代并没有结束,因为实际上它们被视为LocalTime,而实际上是在祖鲁时代.

The issue is that jersey/jackson's java time modules parse the timestamps using the ISO format and the regular LocalDateTime#parse methods. I realised that my times are no off since they are being treated as LocalTime while in fact they are in Zulu time.

推荐答案

您误解了引用类文档:

ISO-8601日历系统中没有时区的日期时间,例如{@code 2007-12-03T10:15:30}.

A date-time without a time-zone in the ISO-8601 calendar system, such as {@code 2007-12-03T10:15:30}.

...

此类不存储或表示时区.相反,它是对用于生日的日期的描述,以及在墙上时钟上看到的本地时间.如果没有其他信息(例如偏移量或时区),则无法在时间轴上表示时刻.

This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

因此,其明确的目的只是表示日期和时间而没有时区.表示不是的目的是表示本地时区中的日期和时间 .

So it's explicit purpose is just to represent a date and time without a time-zone. It's porpose is not to represent a date and time in the local time zone.

因此,每次转换只会剥离时区.

Therefore each conversion just strips the time zone.

因此,出于您的目的,您需要在第三个示例中已使用的带有ZoneId.systemDefault()ZonedDateTime.

So for your purposes you need a ZonedDateTime with ZoneId.systemDefault() as you already used in your third example.

第二个例子可能是:

String ts = "2016-09-12T13:15:17.309Z";
ZonedDateTime parse = 
    ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME)
        .withZoneSameInstant(ZoneId.systemDefault());
System.out.println(parse);
System.out.println(parse.toLocalDateTime());

这篇关于与Java时间解析UTC混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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