将UTC中的ISO 8601字符串转换为本地时间 - JodaTime正在添加与本地时区相反的字符串

问题描述 投票:1回答:1

说我有一个String等于2019-02-23T07:58:21。这是从UTC中的系统时钟检索的时间。

我想将时间转换为系统当地时间。

我正在使用JodaTime,因为它似乎可以很容易地做我想要的。


我尝试过的:

DateTimeFormatter dateParser = ISODateTimeFormat.dateTimeNoMillis().withZoneUTC();

DateTime dateTime;
LocalDateTime localDateTime;

dateTime = dateParser.parseDateTime("2019-02-22T01:03:23Z");
localDateTime = dateTime.toLocalDateTime();

System.out.println("UTC: " + dateTime.toDate());
System.out.println("Local: " + localDateTime.toDate());

输出的是什么:

UTC: Thu Feb 21 18:03:23 MST 2019
Local: Fri Feb 22 01:03:23 MST 2019

问题:

  • 设置到我系统的默认时区是MST,即UTC-7:00。它看起来实际上是在UTC时间增加了7个小时 - 为什么会这样?
  • 此外,它认为两次都是在MST时间。我原以为.withZoneUTC()会解决这个问题。为什么这么想?
  • 这种方法对于这样做是“最好的”(假设这些问题可以修复)吗?
java datetime timezone jodatime
1个回答
4
投票

我一步一步走:

  1. dateParser.parseDateTime("2019-02-22T01:03:23Z")按照预期2月22日01:03 UTC给你(2月21日18:03在偏离-07:00的同一时间点)。
  2. dateTime.toLocalDateTime()抛出UTC偏移信息,所以你得到2月22日01:03没有时区信息。 LocalDateTime是没有时区信息的日期和时间,因此不对应任何时间点。
  3. dateTime.toDate()为您提供与2月2​​2日01:03 UTC相同的时间点,没有偏移或时区信息。 Date尽管它的名字在某种程度上与LocalDateTime相反:它是一个时间点,但不对应于一天中的任何特定时刻。
  4. "UTC: " + dateTime.toDate()Date附加到一个字符串。为此,隐式调用Date.toString以获取要附加到第一个字符串的字符串。 Date.toString使用您的本地时区来呈现字符串(这种行为会让很多人感到困惑)。所以你得到的时间点打印为Thu Feb 21 18:03:23 MST 2019,这是正确的时间点,只转换为山地标准时间。
  5. localDateTime.toDate()是有问题的。您说要将日期和时间转换为某个时间点。 LocalDateTime通过使用您当地的时区解决了这个问题,所以你得到的时间相当于2月22日,美国夏令时01:03(与UTC时间08:03相同)。
  6. "Local: " + localDateTime.toDate()再次调用toString并使用MST渲染字符串。

它看起来实际上是在UTC时间增加了7个小时 - 为什么会这样?

因为您丢弃了日期和时间以UTC为单位的信息,然后在MST中解释它们。

此外,它认为两次都是在MST时间。 ......为什么这么想?

不是。这只是Date.toString令人困惑的行为。

这种方法对于这样做是“最好的”(假设这些问题可以修复)吗?

如果您正在编写新代码,最好使用现代Java日期和时间API java.time。如果您已经在使用Joda-Time,那么可以开发一个使用Joda-Time的好解决方案,而且您是否以及何时需要迁移到java.time是一个悬而未决的问题。

我对Joda-Time没有经验,但是这里有一个使用java.time的片段,如果你想要的话:

    String systemUtcString = "2019-02-22T01:03:23Z";
    Instant pointInTime = Instant.parse(systemUtcString);
    ZonedDateTime denverDateTime = pointInTime.atZone(ZoneId.of("America/Denver"));
    System.out.println(denverDateTime);

2019-02-21T18:03:23-07:00 [美国/丹佛]

在任何情况下,如果可以,请避免使用java.util.Date。只有当您不可或缺地需要Date用于遗留API时,您无法更改或者不想立即更改,请在调用该API之前进行转换。在这种情况下,请记住Date没有时区,因此在转换为Date之前无需转换为MST。

    Date oldfashionedDateObject = Date.from(pointInTime);
    System.out.println(oldfashionedDateObject);

2月21日星期四18:03:23 2018年MST

引用

请注意,Joda-Time被认为是一个很大程度上“完成”的项目。没有计划重大改进。如果使用Java SE 8,请迁移到java.time(JSR-310)。

(来自Joda-Time主页)

链接

© www.soinside.com 2019 - 2024. All rights reserved.