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

时间:2019-02-23 22:00:11

标签: java datetime timezone jodatime

说我有一个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()可以解决这个问题。为什么会这样想?

  • 此方法是否是执行此操作的“最佳”方法(假设这些问题可以 是固定的)?

1 个答案:

答案 0 :(得分:4)

我将逐步进行:

  1. dateParser.parseDateTime("2019-02-22T01:03:23Z")为您提供了2月22日世界标准时间01:03的预期时间(与2月21日18:03的时间相同,偏移量为-07:00)。
  2. dateTime.toLocalDateTime()丢掉了UTC偏移量信息,因此您在2月22日的01:03上没有时区信息。 LocalDateTime是没有时区信息的日期和时间,因此不对应任何时间点。
  3. dateTime.toDate()为您提供与2月2​​2日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(与世界标准时间08:03相同)。
  6. "Local: " + localDateTime.toDate()再次调用toString并使用MST呈现字符串。
  

看起来实际上是将UTC时间增加了 7小时-为什么?

因为您丢弃了日期和时间在UTC中的信息,然后在MST中对其进行了解释。

  

此外,它认为两个时间都是MST时间。 …为什么这样想?

不是。只是Date.toString令人困惑。

  

此方法是否是执行此操作的“最佳方法”(假设可以解决这些问题)?

如果您要编写新代码,最好使用java.time(现代的Java日期和时间API)。如果您已经在使用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);
  

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

报价

  

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

(来自Joda-Time主页)

链接