将特定时区的时间转换为其他会计夏令时

Convert Time of a particular time zone to other accounting daylight savings

我有一个 DateTime 字段代表日期和时间,还有一个单独的 zone 字符串告诉它的时区。

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

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

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

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

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 in Europe/London equals 2021-01-13T18:45-05:00[America/Toronto]

如果所涉及的两个时区中的任何一个使用夏令时 (DST),转换会自动考虑夏令时。

编辑:您似乎假设日期和时间是当前的,而不是历史的?您提到 America/Sao_Paulo 减少了 2019 年的夏令时——如果您有 2019 年或更早的 LocalDateTime 怎么办?如果你不打算正确处理这些,你绝对应该对你的日期时间进行范围检查,如果超出你的预期范围则拒绝转换它。使用isBeforeand/orisAfter方法LocalDateTime.

Link: Oracle tutorial: Date Time 解释如何使用 java.time.