CET
是一个伪区
永远不要使用 2-4 个字母的缩写,例如EST
或IST
因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
Continent/Region
以、或等格式指定适当的时区名称。Continent/Region
America/Montreal
Africa/Casablanca
Pacific/Auckland
也许CET
您实际上是指时区,例如Europe/Luxembourg
or Europe/Gibraltar
。
ZoneId zoneId = ZoneId.of( "Europe/Gibralter" ) ;
该类TimeZone
现在是遗留的,是与 Java 的最早版本捆绑在一起的可怕日期时间类的一部分。只使用现代的java.time类。
为 DST 调整专有名称
由于该程序没有定期重新启动(它是一个服务器),我想知道当我们从冬季切换到夏季时会发生什么?
如果您使用如上所示的正确名称,并且在您的 JVM 安装中保持tzdata数据文件是最新的,那么在使用ZonedDateTime
.
ZonedDateTime zdt = ZonedDateTime.now() ; // Omitting the optional `ZoneId` argument means the JVM’s current default time zone is implicitly applied, looking up the current offset in use at this moment for the JVM's current default time zone.
让我们看看在 2020 年春季(即 3 月 29 日凌晨 2 点)夏令时切换期间会发生什么。我们得到的时间是凌晨 2 点前的一分钟。然后我们加一分钟。请注意,由于挂钟时间的 DST“提前”调整,一天中的时间如何从凌晨 1:59 跳转到凌晨 3 点而不是凌晨 2 点。
ZoneId z = ZoneId.of( "Europe/Gibraltar" ) ;
ZonedDateTime zdt = ZonedDateTime.of( 2020 , 3 , 29 , 1 , 59 , 0 , 0 , z ) ;
ZonedDateTime zdtMinuteLater = zdt.plusMinutes( 1 ) ; // Notice how the time-of-day jumps to 3 AM rather than 2 AM.
转储到控制台。
System.out.println( "zdt.toString(): " + zdt ) ;
System.out.println( "zdtMinuteLater.toString(): " + zdtMinuteLater ) ;
请参阅在 IdeOne.com 上实时运行的代码。
zdt.toString(): 2020-03-29T01:59+01:00[欧洲/直布罗陀]
zdtMinuteLater.toString(): 2020-03-29T03:00+02:00[欧洲/直布罗陀]
不要依赖默认值
您可以编写代码以不依赖 JVM 当前的默认时区。
前面显示的代码行 ( ZonedDateTime.now()
)不是我推荐的。该行省略了可选ZoneId
参数。相反,我建议始终通过您想要/预期的时区。
ZoneId zoneId = ZoneId.of( "Europe/Gibralter" ) ;
ZonedDateTime zdtGibralter = ZonedDateTime.now( zoneId ) ;