如何从本地和 UTC 时间戳 java 获取时区

How to get timezone from local and UTC timestamps java

提问人:saurabh.kg001 提问时间:10/20/2023 最后编辑:Anonymoussaurabh.kg001 更新时间:10/21/2023 访问量:72

问:

我有一个用例,其中作为输入的数据不指定时区,但是我们有两个单独的字段“local”和“utc”,它们实际上可以表示偏移量,从而表示时区。

我想获取时区,以便我能够将UTC中提供的另一个时间转换为相应的本地时间。

输入:

transaction_date_local transaction_date_utc
2023-05-01 07:00:23.021 2023-05-01T14:00:23.021Z

基于此,我想将另一个时间从UTC转换为本地
时间,例如 = ,应转换为本地时间 (
query_time_utcquery_time_utc2023-06-01 06:59:59query_time_local)

我们怎样才能做到这一点?我正在考虑获取本地时间和 UTC 时间之间的差异,然后将该差异应用于可用的 UTC 时间以获取本地时间。但是,想检查是否有更高级别的 API 可用。

感谢对此的支持(最好是 Java / Scala)

java datetime timezone datetime-conversion

评论

3赞 user85421 10/20/2023
相关 是否可以确定两个时间戳的 UTC 偏移量? ?
0赞 Basil Bourque 10/21/2023
错字?您是否打算在“query_time_utc = 2023-06-01 06:59:59”的末尾添加一个?这使您的问题非常混乱。Z
0赞 Anonymous 10/21/2023
这听起来可能很简单。事实并非如此。我们知道您的未知时区位于 5 月 1 日的 UTC 偏移量 -07:00,但由于夏令时转换或其他时间异常,它可能在其他时间处于不同的 UTC 偏移量(实际上不是在同一年的 6 月 1 日,但您希望您的代码也适用于其他日期)。
0赞 Anonymous 10/21/2023
一个选项是循环访问定义了 UTC 偏移量的所有时区,并将每个时区应用于新的 UTC 时间戳,以获取候选本地时间。在大多数情况下,您可能最终只有 2 或 3 个不同的可能当地时间,有时只有 1 个。

答:

1赞 Basil Bourque 10/21/2023 #1

许多时区可能共享一个偏移量

表示偏移量,从而表示时区

否,偏移量不表示时区。许多时区可以共享特定的偏移量。

例如,美国/伊努维克、美国/博伊西、美国/耶洛奈夫、美国/Cambridge_Bay、美国/Ciudad_Juarez、美国/凤凰城、美国/道森、美国/Dawson_Creek、美国/埃德蒙顿、美国/Fort_Nelson、美国/埃莫西约、美国/马萨特兰、美国/丹佛、美国/怀特霍斯、美国/蒂华纳、美国/Los_Angeles和美国/温哥华等时区可能会使用比 UTC 晚 7 小时的偏移量。

偏移量与时区的关系

偏移量仅是时间子午线(如 UTC)之前或之后的小时-分钟-秒数。

时区是特定地区人民使用的偏移量的过去、现在和未来变化的命名历史,由他们的政治家决定。

时刻

日期时间字符串末尾的 A 是 的标准缩写,与 UTC 的时间子午线偏移量为 0 小时-分钟-秒。Z+00:00

将标准 ISO 8601 格式的字符串解析为 .ZInstant

Instant instant = Instant.parse( "2023-05-01T14:00:23.021Z" ) ;

要通过特定地区人们使用的挂钟/日历查看时刻,请应用时区 () 以获得 .ZoneIdZonedDateTime

ZoneId zTokyo = ZoneId .of( "Asia/Tokyo" ) ;
ZonedDateTime zdtTokyo = instant.atZone( zTokyo ) ;

ZoneId zDawsonCreek = ZoneId .of( "America/Dawson_Creek" ) ;
ZonedDateTime zdtDawsonCreek = instant.atZone( zDawsonCreek ) ;

这三个对象 、 、 和 都表示相同的同时时刻,即时间轴上的同一点instantzdtTokyozdtDawsonCreek

看到代码在 Ideone.com 运行

instant.toString() = 2023-05-01T14:00:23.021Z
zdtTokyo.toString() = 2023-05-01T23:00:23.021+09:00[Asia/Tokyo]
zdtDawsonCreek.toString() = 2023-05-01T07:00:23.021-07:00[America/Dawson_Creek]

一刻也没有

缺少偏移量或区域指示符的日期随时间变化的字符串被解析为对象。LocalDateTime

将中间的 SPACE 替换为 符合 ISO 8601 标准。T

LocalDateTime ldt = LocalDateTime.parse( "2023-05-01 07:00:23.021".replace( " " , "T" ) )

代表一个时刻,不是时间轴上的一个点。因此,LocalDateTime 对象本质上是不明确的。在您的示例中,我们看到每月第一天早上 7 点。但无法知道这是否意味着东京的早上 7 点、图卢兹的早上 7 点或美国俄亥俄州托莱多的早上 7 点——三个不同的时刻,相隔几个小时。LocalDateTime

如果您确定缺少区域/偏移量的此类字符串旨在表示在特定时区中看到的 momoet,则可以应用该区域。

ZonedDateTime zdtTokyo = ldt.atZone( zTokyo );

但理想的解决方案是教育数据发布者至少包括 ISO 8601 标准的偏移量。更好的是,还可以将时区名称附加在方括号中,按照类中使用的 ISO 8601 格式进行明智的扩展。java.time.ZonedDateTime

转换

再转换一次......从UTC到本地

是的,您可以从 UTC 中看到的时刻调整为特定时区中看到的提升。如上所示。但是您需要知道时区。

您不能假设偏移量。人们确实会改变他们的偏移量,这种变化是由政客的一时兴起推动的。这些奇思妙想随时可能发生变化。因此,您无法知道将来可能生效的偏移量