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

标签 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. 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() 为您提供与 UTC 2 月 22 日 01:03 相同的时间点,没有偏移量或时区信息。 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 MST(与 08:03 UTC 相同)。
  6. "Local: "+ localDateTime.toDate() 再次调用 toString 并使用 MST 呈现字符串。

It looks like it's actually adding 7 hours to the UTC time - why is that?

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

Additionally, it thinks both times are in MST time. … Why is it thinking this?

不是。这只是 Date.toString 的表现令人困惑。

Is this method the "best" for doing this (assuming these problems can be fixed)?

如果您要编写新代码,最好使用现代 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[America/Denver]

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

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

Thu Feb 21 18:03:23 MST 2019

报价

Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).

(来自 Joda-Time 主页)

链接

关于java - 将 UTC 中的 ISO 8601 字符串转换为本地时间 - JodaTime 添加与本地时区相反的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54846652/

相关文章:

java - 解析日期时无法从 TemporalAccessor 获取 ZonedDateTime

datetime - 为什么我在 rails_admin 显示 View 中看不到日期时间字段?

c# - 如何通过 UTC 偏移量确定时区?

java - 如何在JavaEE(@Inject)中使用模拟@Autowired注释?

java - OpenCV 模板匹配 Max Min 取值范围是多少?需要作为theshold/c++/java

java - Infix转postfix有公式吗?

java - 如何模拟影响对象的无效返回方法

javascript - 使用 moment 抓取不同时区的日期的部分内容

javascript - Debian Jenny 上的 Node 不使用本地时区

javascript - 将 "Thu Sep 19 14:24:59 UTC 2019"转换为时刻日期