Java 以region/city形式使用 IANA 时区 ID 。所以如果你能把你的缩写映射到那些,你就可以通过。为了给你工作代码,这里有一个例子,但我保证有些 ID 不是你想要的。您必须定义自己的映射。您列表中的某些长时区名称并不指代唯一时区,例如海湾标准时间和中欧时间。这些区域内有许多时区。
private static final Map<String, String> tzSubset = Map.ofEntries(
Map.entry("NZST", "Antarctica/McMurdo"),
Map.entry("AEST", "Australia/Sydney"),
Map.entry("JST", "Asia/Tokyo"),
Map.entry("HKT", "Asia/Hong_Kong"),
Map.entry("CST", "America/North_Dakota/New_Salem"), // not in China
Map.entry("SGT", "Asia/Singapore"),
Map.entry("IST", "Asia/Calcutta"),
Map.entry("GST", "Asia/Dubai"),
Map.entry("MSK", "Europe/Volgograd"),
Map.entry("SAST", "Africa/Mbabane"),
Map.entry("CET", "Africa/Ceuta"),
Map.entry("GMT", "Etc/GMT"),
Map.entry("BST", "Europe/Belfast"),
Map.entry("BRT", "America/Maceio"),
Map.entry("ET", "America/Indiana/Winamac")
);
private static final ZoneId targetTimeZone = ZoneId.of("America/Toronto");
有了映射和所需的时区,转换就足够简单了:
LocalDateTime inputDateTime = LocalDateTime.of(2021, Month.JANUARY, 13, 23, 45);
String inputTimeZone = "BST";
ZoneId zone = ZoneId.of(inputTimeZone, tzSubset);
ZonedDateTime targetDateTime = inputDateTime.atZone(zone)
.withZoneSameInstant(targetTimeZone);
System.out.format("%s in %s equals %s%n", inputDateTime, zone, targetDateTime);
此示例代码段的输出为:
2021-01-13T23:45 在欧洲/伦敦等于 2021-01-13T18:45-05:00[美国/多伦多]
如果涉及的两个时区中的任何一个使用夏令时 (DST),则转换会自动考虑夏令时。
编辑:您似乎假设日期和时间是当前的,而不是历史的?您提到 America/Sao_Paulo 在 2019 年取消了夏季时间——那么如果您有LocalDateTime
2019 年或更早的时间呢?如果您不打算正确处理这些问题,您绝对应该对您的日期时间进行范围检查,如果超出您的预期范围,则拒绝转换。使用isBefore
和/或 的isAfter
方法LocalDateTime
。
链接: Oracle 教程:解释如何使用 java.time 的日期时间。