说我的 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()
可以解决这个问题。为什么这么认为?是这样做的"最佳"(假设这些问题可以修复)?
我逐步进行:
-
dateParser.parseDateTime("2019-02-22T01:03:23Z")
在UTC的2月22日为您提供了预期的2月22日(与2月21日的时间点相同的时间点 - 07:00)。 -
dateTime.toLocalDateTime()
将UTC偏移信息丢弃,因此您在01:03获得2月22日,没有时区信息。LocalDateTime
是没有时区信息的日期和一天中的时间,因此与任何时间点不符。 -
dateTime.toDate()
为您提供与2月22日在01:03 UTC的时间点相同的时间点,而无需偏移或时区信息。尽管Date
的名称是某种程度上的LocalDateTime
:它是一个时间点,但与一天中的任何特定小时都不相对。 -
"UTC: " + dateTime.toDate()
将Date
附加到字符串。为此,隐式调用Date.toString
以获取一个字符串以附加到第一个字符串。Date.toString
使用您本地时区渲染字符串(此行为使许多人感到困惑)。因此,您获得的时间点被打印为Thu Feb 21 18:03:23 MST 2019
,这是正确的时间点,仅转换为山区标准时间。 -
localDateTime.toDate()
是有问题的。您是说要将日期和时间转换为一个时间点。LocalDateTime
通过使用您的本地时区解决此问题,因此您可以获得等于22的时间点,在01:03 MST(与08:03 UTC相同的点)。 -
"Local: " + localDateTime.toDate()
再次调用toString
并使用MST渲染字符串。
看起来它实际上是在UTC时间添加 7个小时 - 为什么?
因为您正在丢弃日期和时间在UTC中的信息,然后在MST中解释它们。
此外,它都认为这两次都在MST。…为什么要这么想?
不是。只是Date.toString
令人困惑。
此方法是这样做的"最佳"(假设可以解决这些问题)?
如果您正在编写新代码,最好使用Java。Time,现代Java日期和时间API。如果您已经在使用Joda Time,则可以开发与Joda Time的好解决方案,这是一个悬而未决的问题
我没有Joda Time的经验,但是这里是使用Java的片段。
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);
thu 2月21日18:03:23 MST 2019
QUOTE
请注意,Joda Time被认为是一个"完成"项目。 没有计划进行重大增强。如果使用Java SE 8,请迁移 到
java.time
(JSR-310)。
(摘自Joda Time Homepeg)
链接
- Oracle教程:解释如何使用Java.Time的日期时间。
- Joda Time主页。