Java. 根据时区名称将EDT、CDT、CST等时区的时间转换为UTC

3
我有一个API,返回时间和时区分开。
time: "2018-12-18 16:00:28"

timezone: "EDT"

我该如何将其解析为UTC时间?

API返回的时区有:EDT、CDT、CST、EST等。

我尝试在Java库java.timejava.util.TimeZone中寻找解决方案,但它们不能处理某些时区名称。


4
这些仅有三个字母的简称通常不是唯一的。例如IST既可以表示以色列标准时间,也可以表示印度标准时间等,因此可能会得到意料之外的结果。 - RealSkeptic
你说得对,以这种方式发送时区是一个糟糕的想法,不幸的是,我无法更改遗留系统。 - Olesia Ilchuk
比如说,按照CST,你是想要澳大利亚中部时间、北美中部时间、古巴标准时间还是中国标准时间?如果这个时间在一年的夏令时部分,你是想要夏令时还是仍然想要标准时间? - Ole V.V.
2个回答

4

将您的字符串连接在一起,以便它们可以一起解析。然后,您可以解析为ZonedDateTime,然后将时区更改为您想要的任何时区。

String timestamp = "2018-12-18 16:00:28";
String zone = "EDT";
String timeWithZone = timestamp + ' ' + zone;

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.ISO_LOCAL_DATE)
    .appendLiteral(' ')
    .append(DateTimeFormatter.ISO_LOCAL_TIME)
    .appendLiteral(' ')
    .appendPattern("z") // Zone
    .toFormatter();

ZonedDateTime edt = ZonedDateTime.parse(timeWithZone, formatter);
ZonedDateTime utc = edt.withZoneSameInstant(ZoneId.of("UTC"));

2
还有 ZoneOffset.UTC - assylias
在我的Java 9中,EST和EDT都会给出America/New_York,CST和CDT都会给出SystemV/CST6CDT。您可能需要检查是否符合要求。您还可以验证,在冬天的日期中不会得到EDT或在夏天的日期中不会得到CST,例如。验证方法是:使用相同的格式化程序将ZonedDateTime重新格式化,看看是否再次获得相同的字符串。 - Ole V.V.

2
您可以将其解析为LocalDateTime,然后手动设置TimeZone
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime= LocalDateTime.parse("2018-12-18 16:00:28", formatter);
ZonedDateTime zonedDateTime = localDateTime
        .atZone(ZoneId.of("EST", ZoneId.SHORT_IDS))
        .withZoneSameInstant(ZoneId.of("UTC", ZoneId.SHORT_IDS));

我建议使用ZoneId.of("EST", ZoneId.SHORT_IDS),这样可以避免使用过时的TimeZone类(结果将是相同的)。在下一行中使用ZoneOffset.UTC(将起作用)。 - Ole V.V.
这个解决方案只适用于少数时区。对于EDT,我会收到异常“未知的时区ID:EDT”。 - Olesia Ilchuk
1
@OlesiaIlchuk 是的,你需要填充传递给 ZoneId.of 的地图,以获取所需的时区缩写。 SHORT_IDS 可以作为起点,但不包含夏令时(DST)版本。你得到的回报是对缩写如何解释拥有完全控制权。我认为这非常关键。 - Ole V.V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接