将特定时区的时间转换为其他会计夏令时
Convert Time of a particular time zone to other accounting daylight savings
我有一个 DateTime
字段代表日期和时间,还有一个单独的 zone
字符串告诉它的时区。
我想将 DateTime
的时间转换为东部时区。
我找到了几个解释这一点的答案,但它们都使用 IANA 的 Continent/Region 区域 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
进行相应的转换。
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
怎么办?如果你不打算正确处理这些,你绝对应该对你的日期时间进行范围检查,如果超出你的预期范围则拒绝转换它。使用isBefore
and/orisAfter
方法LocalDateTime
.
Link: Oracle tutorial: Date Time 解释如何使用 java.time.
我有一个 DateTime
字段代表日期和时间,还有一个单独的 zone
字符串告诉它的时区。
我想将 DateTime
的时间转换为东部时区。
我找到了几个解释这一点的答案,但它们都使用 IANA 的 Continent/Region 区域 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
进行相应的转换。
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
怎么办?如果你不打算正确处理这些,你绝对应该对你的日期时间进行范围检查,如果超出你的预期范围则拒绝转换它。使用isBefore
and/orisAfter
方法LocalDateTime
.
Link: Oracle tutorial: Date Time 解释如何使用 java.time.