如何在 Java 中指定夏令时转换后的时间
How to specify time after daylight saveing time shift in Java
使用以下代码:
class Test {
public static void main(String [] args) {
LocalDate date = LocalDate.of(2018, 11, 4);
LocalTime time = LocalTime.of(1, 59);
ZonedDateTime dt = ZonedDateTime.of(date, time, ZoneId.of("America/New_York"));
System.out.println(dt.getHour() + ":" + dt.getMinute() + ":" + dt.getSecond());
dt = dt.plusMinutes(1);
System.out.println(dt.getHour() + ":" + dt.getMinute() + ":" + dt.getSecond());
dt = dt.plusMinutes(59);
System.out.println(dt.getHour() + ":" + dt.getMinute() + ":" + dt.getSecond());
dt = dt.plusMinutes(1);
System.out.println(dt.getHour() + ":" + dt.getMinute() + ":" + dt.getSecond());
}
}
我明白了
1:59:0
1:0:0
1:59:0
2:0:0
有没有办法从夏令时后到达 1:00:00 而无需经过夏令时前的 1:00:00?
使用 ofStrict
指定您希望生成的分区日期时间位于哪个偏移量上。 America/New_York
在相关时间左右从 -04:00 更改为 -05:00,因此您需要 ZoneOffset.ofHours(-5)
.
ZonedDateTime dt = ZonedDateTime.ofStrict(
LocalDateTime.of(date, time),
ZoneOffset.ofHours(-5),
ZoneId.of("America/New_York")
);
如果您无法硬编码偏移量,您可以使用以下方法获取偏移量:
var dateTime = LocalDateTime.of(date, time)
var zone = ZoneId.of("America/New_York");
var offsetAfter = zone.getRules()
.getTransition(dateTime)
.getOffsetAfter();
ZonedDateTime dt = ZonedDateTime.ofStrict(
dateTime,
offsetAfter,
zone
);
或者,作为 Ole V.V。指出,你也可以使用更短的:
ZonedDateTime dt = ZonedDateTime.of(
date, time, ZoneId.of("America/New_York")
).withLaterOffsetAtOverlap();
遵守夏令时的时区的问题是这样的时间不明确。 “America/New_York”区域有两个标记为 2008-11-04T01:00:00 的时间。从技术上讲,其中一个是 01:00 EDT,另一个是 01:00 EST,但不是很多软件都会让你这样区分,尤其是因为这样的 three-letter 时区指定不一定是全球唯一的。
解决方案是指定没有夏令时的世界时间或相对于世界时间的时间:第一个 01:00 东部时间是 05:00Z,第二个是 06:00Z。因此,您可以将时间作为其中之一,将时区作为“UTC”(然后将结果转换为“America/New_York”),或者指定偏移量 from UTC使用 ofStrict
.
使用以下代码:
class Test {
public static void main(String [] args) {
LocalDate date = LocalDate.of(2018, 11, 4);
LocalTime time = LocalTime.of(1, 59);
ZonedDateTime dt = ZonedDateTime.of(date, time, ZoneId.of("America/New_York"));
System.out.println(dt.getHour() + ":" + dt.getMinute() + ":" + dt.getSecond());
dt = dt.plusMinutes(1);
System.out.println(dt.getHour() + ":" + dt.getMinute() + ":" + dt.getSecond());
dt = dt.plusMinutes(59);
System.out.println(dt.getHour() + ":" + dt.getMinute() + ":" + dt.getSecond());
dt = dt.plusMinutes(1);
System.out.println(dt.getHour() + ":" + dt.getMinute() + ":" + dt.getSecond());
}
}
我明白了
1:59:0
1:0:0
1:59:0
2:0:0
有没有办法从夏令时后到达 1:00:00 而无需经过夏令时前的 1:00:00?
使用 ofStrict
指定您希望生成的分区日期时间位于哪个偏移量上。 America/New_York
在相关时间左右从 -04:00 更改为 -05:00,因此您需要 ZoneOffset.ofHours(-5)
.
ZonedDateTime dt = ZonedDateTime.ofStrict(
LocalDateTime.of(date, time),
ZoneOffset.ofHours(-5),
ZoneId.of("America/New_York")
);
如果您无法硬编码偏移量,您可以使用以下方法获取偏移量:
var dateTime = LocalDateTime.of(date, time)
var zone = ZoneId.of("America/New_York");
var offsetAfter = zone.getRules()
.getTransition(dateTime)
.getOffsetAfter();
ZonedDateTime dt = ZonedDateTime.ofStrict(
dateTime,
offsetAfter,
zone
);
或者,作为 Ole V.V。指出,你也可以使用更短的:
ZonedDateTime dt = ZonedDateTime.of(
date, time, ZoneId.of("America/New_York")
).withLaterOffsetAtOverlap();
遵守夏令时的时区的问题是这样的时间不明确。 “America/New_York”区域有两个标记为 2008-11-04T01:00:00 的时间。从技术上讲,其中一个是 01:00 EDT,另一个是 01:00 EST,但不是很多软件都会让你这样区分,尤其是因为这样的 three-letter 时区指定不一定是全球唯一的。
解决方案是指定没有夏令时的世界时间或相对于世界时间的时间:第一个 01:00 东部时间是 05:00Z,第二个是 06:00Z。因此,您可以将时间作为其中之一,将时区作为“UTC”(然后将结果转换为“America/New_York”),或者指定偏移量 from UTC使用 ofStrict
.