0

我有一个DateTime表示日期和时间的字段,以及一个zone告诉其时区的单独字符串。

我想将时间转换DateTime为东部时区。

我找到了几个解释这一点的答案,但它们都使用 IANA 的大陆/地区区域 ID 命名标准进行转换。我zone从用户那里获得了区域 ID 的简短格式符号,例如 IST、AEST、CST 等。有没有办法可以使用简短符号将时间转换为东部时间格式?

更新: 我有一组有限的时区,可以作为输入给出。它们如下:

  • JST- 日本标准时间 (+09:00)
  • CST- 中国标准时间 (+08:00)
  • SAST- 南非标准时间 (+02:00)
  • GMT- 格林威治标准时间 (00:00)
  • EST- 东部时区 (-05:00 / -04:00)
  • HKT- 香港时间 (+08:00)
  • IST- 印度标准时间 (+05:30)

转换策略应注意 DST。因此,如果输入是2021-01-06T10:30:00并且给定的时区是IST. 将其转换为 EST 时的方法应确定 DST 是否适用,并相应地进行-05:00转换-04:00

4

1 回答 1

0

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 年取消了夏季时间——那么如果您有LocalDateTime2019 年或更早的时间呢?如果您不打算正确处理这些问题,您绝对应该对您的日期时间进行范围检查,如果超出您的预期范围,则拒绝转换。使用isBefore和/或 的isAfter方法LocalDateTime

链接: Oracle 教程:解释如何使用 java.time 的日期时间。

于 2021-01-13T06:06:09.270 回答