java.time:CET时区是否考虑夏令时?

2022-09-03 05:04:13

我使用Java 8的新实现,并想知道UTC到CET时间转换结果的输出。java.time

ZonedDateTime utcTime = ZonedDateTime.of(2014, 7, 1, 8, 0, 0, 0, ZoneId.of("UTC"));
ZonedDateTime cetTime = ZonedDateTime.ofInstant(utcTime.toInstant(), ZoneId.of("CET"));
System.out.println("Summer-UTC-Time: " + utcTime);
System.out.println("Summer-CET-Time: " + cetTime);

System.out.println();

utcTime = ZonedDateTime.of(2014, 1, 1, 8, 0, 0, 0, ZoneId.of("UTC"));
cetTime = ZonedDateTime.ofInstant(utcTime.toInstant(), ZoneId.of("CET"));
System.out.println("Winter-UTC-Time: " + utcTime);
System.out.println("Winter-CET-Time: " + cetTime);

我本以为CET时间总是UTC时间的+1,但我得到了:

Summer-UTC-Time: 2014-07-01T08:00Z[UTC]
Summer-CET-Time: 2014-07-01T10:00+02:00[CET] -> +2 **Unexpected**

Winter-UTC-Time: 2014-01-01T08:00Z[UTC]
Winter-CET-Time: 2014-01-01T09:00+01:00[CET] -> +1 Expected

因此,显然我必须处理夏令时,这是我在使用CET时没有预料到的。欧洲中部时间是真正的欧洲中部经济技术标准时间吗?如果是,如果我需要CET,我应该使用哪个区域?java.time


答案 1

IANA 对 CET 的定义是遵循中欧的时区规则,包括冬季和夏季时间。规则可以在这里看到,这表明“CET”是基于“C-Eur”,其中包括夏令时。

您还可以看到完整的规则集:java.time

ZoneId zone = ZoneId.of("CET");
System.out.println(zone);
System.out.println(zone.getRules());
for (ZoneOffsetTransition trans : zone.getRules().getTransitions()) {
  System.out.println(trans);
}
for (ZoneOffsetTransitionRule rule : zone.getRules().getTransitionRules()) {
  System.out.println(rule);
}

哪些打印:

CET
ZoneRules[currentStandardOffset=+01:00]
Transition[Gap at 1916-04-30T23:00+01:00 to +02:00]
Transition[Overlap at 1916-10-01T01:00+02:00 to +01:00]
Transition[Gap at 1917-04-16T02:00+01:00 to +02:00]
Transition[Overlap at 1917-09-17T03:00+02:00 to +01:00]
Transition[Gap at 1918-04-15T02:00+01:00 to +02:00]
Transition[Overlap at 1918-09-16T03:00+02:00 to +01:00]
Transition[Gap at 1940-04-01T02:00+01:00 to +02:00]
Transition[Overlap at 1942-11-02T03:00+02:00 to +01:00]
Transition[Gap at 1943-03-29T02:00+01:00 to +02:00]
Transition[Overlap at 1943-10-04T03:00+02:00 to +01:00]
Transition[Gap at 1944-04-03T02:00+01:00 to +02:00]
Transition[Overlap at 1944-10-02T03:00+02:00 to +01:00]
Transition[Gap at 1945-04-02T02:00+01:00 to +02:00]
Transition[Overlap at 1945-09-16T03:00+02:00 to +01:00]
Transition[Gap at 1977-04-03T02:00+01:00 to +02:00]
Transition[Overlap at 1977-09-25T03:00+02:00 to +01:00]
Transition[Gap at 1978-04-02T02:00+01:00 to +02:00]
Transition[Overlap at 1978-10-01T03:00+02:00 to +01:00]
Transition[Gap at 1979-04-01T02:00+01:00 to +02:00]
Transition[Overlap at 1979-09-30T03:00+02:00 to +01:00]
Transition[Gap at 1980-04-06T02:00+01:00 to +02:00]
Transition[Overlap at 1980-09-28T03:00+02:00 to +01:00]
Transition[Gap at 1981-03-29T02:00+01:00 to +02:00]
Transition[Overlap at 1981-09-27T03:00+02:00 to +01:00]
Transition[Gap at 1982-03-28T02:00+01:00 to +02:00]
Transition[Overlap at 1982-09-26T03:00+02:00 to +01:00]
Transition[Gap at 1983-03-27T02:00+01:00 to +02:00]
Transition[Overlap at 1983-09-25T03:00+02:00 to +01:00]
Transition[Gap at 1984-03-25T02:00+01:00 to +02:00]
Transition[Overlap at 1984-09-30T03:00+02:00 to +01:00]
Transition[Gap at 1985-03-31T02:00+01:00 to +02:00]
Transition[Overlap at 1985-09-29T03:00+02:00 to +01:00]
Transition[Gap at 1986-03-30T02:00+01:00 to +02:00]
Transition[Overlap at 1986-09-28T03:00+02:00 to +01:00]
Transition[Gap at 1987-03-29T02:00+01:00 to +02:00]
Transition[Overlap at 1987-09-27T03:00+02:00 to +01:00]
Transition[Gap at 1988-03-27T02:00+01:00 to +02:00]
Transition[Overlap at 1988-09-25T03:00+02:00 to +01:00]
Transition[Gap at 1989-03-26T02:00+01:00 to +02:00]
Transition[Overlap at 1989-09-24T03:00+02:00 to +01:00]
Transition[Gap at 1990-03-25T02:00+01:00 to +02:00]
Transition[Overlap at 1990-09-30T03:00+02:00 to +01:00]
Transition[Gap at 1991-03-31T02:00+01:00 to +02:00]
Transition[Overlap at 1991-09-29T03:00+02:00 to +01:00]
Transition[Gap at 1992-03-29T02:00+01:00 to +02:00]
Transition[Overlap at 1992-09-27T03:00+02:00 to +01:00]
Transition[Gap at 1993-03-28T02:00+01:00 to +02:00]
Transition[Overlap at 1993-09-26T03:00+02:00 to +01:00]
Transition[Gap at 1994-03-27T02:00+01:00 to +02:00]
Transition[Overlap at 1994-09-25T03:00+02:00 to +01:00]
Transition[Gap at 1995-03-26T02:00+01:00 to +02:00]
Transition[Overlap at 1995-09-24T03:00+02:00 to +01:00]
Transition[Gap at 1996-03-31T02:00+01:00 to +02:00]
Transition[Overlap at 1996-10-27T03:00+02:00 to +01:00]
Transition[Gap at 1997-03-30T02:00+01:00 to +02:00]
Transition[Overlap at 1997-10-26T03:00+02:00 to +01:00]
TransitionRule[Gap +01:00 to +02:00, SUNDAY on or after MARCH 25 at 02:00 STANDARD, standard offset +01:00]
TransitionRule[Overlap +02:00 to +01:00, SUNDAY on or after OCTOBER 25 at 02:00 STANDARD, standard offset +01:00]

这里的关键是要了解时区标识符和该标识符的“短名称”是两个不同的元素。标识符始终固定为“CET”,但名称在“CET”和“CEST”之间更改。


答案 2

因为您知道偏移量并且不想使用DTS,为什么不使用方法而不是?ZoneOffset.ofHours(1)ZoneId.of("CET")

此外,您还可以在任何 ZoneId 实例上调用 normalized() 以使其成为固定的偏移量,但听起来不如从一开始就使用偏移量可靠。

From ZoneId javadoc

ZoneId 用于标识用于在即时和 LocalDateTime 之间进行转换的规则。有两种不同类型的 ID:

  • 固定偏移量 - 来自 UTC/格林威治的完全解析偏移量,对所有本地日期时间使用相同的偏移量
  • 地理区域 - 应用一组特定规则来查找与 UTC/格林威治的偏移量的区域

大多数固定偏移由区域偏移表示。在任何 ZoneId 上调用 normalized() 将确保固定偏移 ID 将表示为 ZoneOffset。

如果您没有使用固定偏移量,那么您使用的是地理区域,这意味着它是否观察到DTS取决于区域。PST也是如此。你会看到它遵守DTS,即使夏令时被称为PDT。是的,这令人困惑,但这就是大多数工具的工作方式。阅读完整的 ZoneId javadoc 以获取更全面的解释(本节)。Time-zone IDs


推荐