【问题标题】:Instant vs ZoneDateTime. Converting to another timezone即时与 ZoneDdateTime。转换到另一个时区
【发布时间】:2021-07-25 00:00:10
【问题描述】:

我很难理解 ZoneDateTime - Instant - LocalDateTime 之间的 java.time ,到目前为止,我唯一知道的是:

  • Instant 介于两者之间
  • Instant(在我的理解中)是从时刻 (UTC) 算起的时间戳,与人类时间流逝相关的时间戳,但没有时区
  • Zone 日期时间有 TimeZone
  • Instant 没有时区,但可以在提供时区信息的情况下处理它
  • Lo​​calDate 时间没有时区,无法处理时区,它是一个日期时间,与整个时间流(全局)的延续没有任何关系。

所以我在下面有这个转换

val seoul = "Asia/Seoul"

val zoneId = ZoneId.of(seoul)
val now = ZonedDateTime.now()

val convertedZoneDateTIme = ZonedDateTime.of(now.toLocalDateTime(), zoneId).withZoneSameInstant(ZoneOffset.UTC)
val convertedInstant = now.toInstant().atZone(zoneId)

// expected output
println(convertedInstant.format(DateTimeFormatter.ofPattern(format)))

// not expected output
println(converted.format(DateTimeFormatter.ofPattern(format)))

输出

2021-05-02 03:15:13
2021-05-02 09:15:13

我正在尝试将给定时间转换为另一个时区,这是一个用户移动到不同时区的用例,我需要更新有关存储日期的任何信息。

为什么我得到的第二个值不正确..?为什么我必须先将其转换为 Instant 并继续进行转换?

提前谢谢你

【问题讨论】:

  • 您的“convertedInstant”不是瞬间,而是ZonedDateTime。我的建议:使用显式类型而不是 val。并选择显示时区的格式。然后你会看到第一个结果是 UTC 而第二个结果是韩国区。

标签: java timezone java-time date-conversion zoneddatetime


【解决方案1】:

你的大部分子弹都是完全正确的。正如您在第一个项目符号中所说,只有您不应该使用InstantLocalDateTimeZonedDateTime 之间工作。在InstantLocalDateTime 之间转换需要一个时区(或至少与UTC 有一个偏移量),因此应该通过ZonedDateTime。所以ZonedDateTime 是在其他两个之间使用的那个。正如我所说,其余的都是正确的。

您并不清楚您对代码的期望,也不清楚具体观察到的结果有何不同。假设您想在整个过程中使用相同的时间点,这一行就是您出乎意料的地方:

val convertedZoneDateTIme = ZonedDateTime.of(now.toLocalDateTime(), zoneId).withZoneSameInstant(ZoneOffset.UTC)

now 是您自己的时区中的ZonedDateTime(准确地说是您的 JVM 的默认时区)。通过从中仅获取日期和时间并将它们与不同的时区结合起来,您可以保持一天中的时间,但以这种方式(可能)改变时间流中的点。接下来,您将转换为 UTC,保持时间点(瞬间),从而(可能)更改一天中的时间,并可能更改日期。从作为起点的ZonedDateTime 开始,您一无所有,而且我看不出该操作有意义。要将 now 转换为 UTC 并保持时间轴上的点,请使用更简单的方法:

val convertedZoneDateTIme = now.withZoneSameInstant(ZoneOffset.UTC)

通过此更改,您的两个输出在时间点上达成一致。示例输出:

2021-05-07 02:30:16 +09:00 Korean Standard Time
2021-05-06 17:30:16 +00:00 Z

我使用了format 中的uuuu-MM-dd HH:mm:ss xxx zzzz

对于您的其他转换,我更喜欢使用withZoneSameInstant()。那么我们就不需要通过Instant

val convertedInstant = now.withZoneSameInstant(zoneId)

它给出的结果与您的代码相同。

对所讨论的每个类的内容进行简要概述:

Class Date and time of day Point in time Time zone
ZonedDateTime Yes Yes Yes
Instant - Yes -
LocalDateTime Yes - -

基本上,LocalDateTime 对您的目的没有任何用处,而且Instant 虽然可用,但不是必需的。 ZonedDateTime 就可以满足您的需求。

【讨论】:

  • 我还没有回到我的测试中,但我真的很感谢我简洁地向我解释它的努力。我不认为 ZonedDateTime 单独可以解决我从区域切换到另一个区域的问题。
猜你喜欢
  • 2018-08-12
  • 2019-03-12
  • 1970-01-01
  • 2012-10-27
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
  • 2013-12-03
  • 2014-09-07
相关资源
最近更新 更多