augray 的answer 是正确的,应该被接受(单击那个大的空复选标记图标使其变为绿色)。我会添加一些想法和代码。
使用好的日期时间库
避免 java.util.Date/.Calendar 类的混乱。它们是出了名的麻烦,在设计和实现上都有缺陷。
这些类已被 Java 8 和更高版本 (Tutorial) 中的新 java.time package 取代。该软件包的灵感来自 Joda-Time 库。虽然相似,但 java.time 和 Joda-Time 并不相同。每个都有其他人缺乏的功能。您可以使用其中一个或两个。
避免使用 3-4 个字母的时区代码
CET & CEST 等代码既不标准化也不唯一。避开他们。
使用full time zone names。其中大部分是“大陆/城市”或“大陆/地区”。
您似乎正在使用此代码来解决DST, Daylight Saving Time 的问题。将这些繁重的工作留给日期时间库,例如 java.time 或 Joda-Time。时区将与 UTC 的偏移与 DST 和其他异常的过去、现在和未来规则集相结合。因此,您指定时区名称并让库来确定 DST 何时生效。
夏令时
Daylight Saving Time (DST) for Rome 今年将于 2015 年 10 月 25 日凌晨 3 点结束。时钟回滚以重复凌晨 2 点。所以那天有两个 2:30 次。您可以在下面的示例代码中看到这两个 2:30 时间。
2015-10-25T02:30+02:00[Europe/Rome]
2015-10-25T02:30+01:00[Europe/Rome]
示例代码
以下是 Java 8 的 java.time 中的一些示例代码,以了解 DST 是如何处理的。首先,我们采用一些“本地”日期时间,其中“本地”表示没有附加任何特定时区。然后我们分配罗马时区。之后,我们采用分区值(罗马值)并增加或减少小时数。
歧义
请注意,“罗马凌晨 2:30”的概念在 10 月 25 日毫无意义。您必须知道01:00 或02:00 的偏移量才能正确解释。
ZoneId zone = ZoneId.of( "Europe/Rome" );
System.out.println( "-----| Local |-----------------------------------------\n" );
LocalDateTime local_0130 = LocalDateTime.of( 2015 , Month.OCTOBER , 25 , 1 , 30 );
ZonedDateTime zoned_0130 = ZonedDateTime.of( local_0130 , zone );
LocalDateTime local_0230 = LocalDateTime.of( 2015 , Month.OCTOBER , 25 , 2 , 30 );
ZonedDateTime zoned_0230 = ZonedDateTime.of( local_0230 , zone );
LocalDateTime local_0330 = LocalDateTime.of( 2015 , Month.OCTOBER , 25 , 3 , 30 );
ZonedDateTime zoned_0330 = ZonedDateTime.of( local_0330 , zone );
System.out.println( "local_0130: " + local_0130 + " in zone: " + zone + " is " + zoned_0130 );
System.out.println( "local_0230: " + local_0230 + " in zone: " + zone + " is " + zoned_0230 );
System.out.println( "local_0330: " + local_0330 + " in zone: " + zone + " is " + zoned_0330 + "\n" );
System.out.println( "-----| Add Hours |-----------------------------------------\n" );
ZonedDateTime zoned_0130_plus_1H = zoned_0130.plusHours( 1 );
ZonedDateTime zoned_0130_plus_2H = zoned_0130.plusHours( 2 );
System.out.println( "zoned_0130_plus_1H: " + zoned_0130_plus_1H );
System.out.println( "zoned_0130_plus_2H: " + zoned_0130_plus_2H + "\n" );
System.out.println( "-----| Subtract Hours |-----------------------------------------\n" );
ZonedDateTime zoned_0330_minus_1H = zoned_0330.minusHours( 1 );
ZonedDateTime zoned_0330_minus_2H = zoned_0330.minusHours( 2 );
System.out.println( "zoned_0330_minus_1H: " + zoned_0330_minus_1H );
System.out.println( "zoned_0330_minus_2H: " + zoned_0330_minus_2H + "\n" );
运行时。
-----| Local |-----------------------------------------
local_0130: 2015-10-25T01:30 in zone: Europe/Rome is 2015-10-25T01:30+02:00[Europe/Rome]
local_0230: 2015-10-25T02:30 in zone: Europe/Rome is 2015-10-25T02:30+02:00[Europe/Rome]
local_0330: 2015-10-25T03:30 in zone: Europe/Rome is 2015-10-25T03:30+01:00[Europe/Rome]
-----| Add Hours |-----------------------------------------
zoned_0130_plus_1H: 2015-10-25T02:30+02:00[Europe/Rome]
zoned_0130_plus_2H: 2015-10-25T02:30+01:00[Europe/Rome]
-----| Subtract Hours |-----------------------------------------
zoned_0330_minus_1H: 2015-10-25T02:30+01:00[Europe/Rome]
zoned_0330_minus_2H: 2015-10-25T02:30+02:00[Europe/Rome]