首页 > 解决方案 > Java.time 从偏移量到时区名称

问题描述

尝试将各种时间格式转换为统一格式。

一种格式是

"uuuu-MM-dd'T'HH:mm:ss-5000"

需要转换为时区格式:

"uuuu-MM-dd'T'HH:mm:ss EST"

使用以下代码,但它只将时区指定为“-05:00”,而不是预期的“EST”。

    String targetFormat = "uuuu-MM-dd'T'HH:mm:ss z";
    String origFormat = "uuuu-MM-dd'T'HH:mm:ss.SSSZ";
    String origStr = "2018-02-05T17:25:18.156-0500";
    ZonedDateTime time = ZonedDateTime.parse(origStr, DateTimeFormatter.ofPattern(origFormat));
    String targetStr = time.format(DateTimeFormatter.ofPattern(targetFormat));

上面的输出是:

2018-02-05T17:25:18 -05:00

如何获得预期:

2018-02-05T17:25:18 EST

标签: javadatetime-formatjava-timetimezone-offsetzoneddatetime

解决方案


-05:00实际上不是时区。这只是一个偏移量:比 UTC 晚 5 小时,你不能真正将它映射到一个时区。

在您使用的日期(2018 年 2 月 2 日),有 47 个时区使用-05:00 *,包括美国以外的地区 - 其中许多不称他们的时区为“EST”,例如使用“PET”的利马(秘鲁时间)或波哥大,使用“COT”(哥伦比亚时间)。无论每个地方使用的名称如何,它们都是-05:00在您使用的日期和时间使用的。

无论如何,当您解析诸如 的偏移量-05:00时,由于上面列出的原因,API 无法知道您指的是哪个时区(不止一个,API 本身无法决定)。您必须任意选择一个时区,然后将您的解析转换ZonedDateTime为该时区:

....
ZonedDateTime time = ZonedDateTime.parse(origStr, DateTimeFormatter.ofPattern(origFormat));

// convert to some arbitrary timezone
time = time.withZoneSameInstant(ZoneId.of("America/New_York"));

我选择“America/New_York”是因为它在 2018 年 2 月使用“EST”。这样,您targetStr将:

2018-02-05T17:25:18 EST

将时区名称更改为您想要的名称。请注意,对于 6 月的日期,当纽约实行夏令时时,它将返回“EDT”。


*:我将 JDK 8 与 2018e TZ 数据文件一起使用,因此此数字在您的环境中可能会有所不同。


推荐阅读