Java.time 从偏移量到时区名称

Java.time from offset to timezone name

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

一种格式是

"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

-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 月的日期,当夏令时在纽约生效时,它将 return "EDT".


*:我使用的是 JDK 8 和 2018e TZ 数据文件,所以这个数字在您的环境中可能会有所不同。