如何在 Java 中使用时区解决夏令时问题java.time

2022-08-31 15:06:52

我必须在我的Java应用程序中打印EST时间。我使用以下命令将时区设置为EST:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));

但是,当在此时区中遵循夏令时时时,我的代码不会打印正确的时间(它打印的时间少了1小时)。

如何使代码始终读取正确的时间,而不管是否遵守夏令时?

PS:我尝试将时区设置为EDT,但这并不能解决问题。


答案 1

这是要开始的问题:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));

应全心全意避免使用 3 个字母的缩写,转而使用 TZDB 区域 ID。EST 是东部标准时间 - 标准时间从不遵守 DST;它不是一个真正的全时区名称。它是用于某个时区的一部分的名称。(不幸的是,我还没有遇到一个关于这个“半时区”概念的好术语。

您需要一个完整的时区名称。例如,位于东部时区:America/New_York

TimeZone zone = TimeZone.getTimeZone("America/New_York");
DateFormat format = DateFormat.getDateTimeInstance();
format.setTimeZone(zone);

System.out.println(format.format(new Date()));

答案 2

其他答案是正确的,特别是Jon Skeet的答案,但已经过时了。

java.time

这些旧的日期时间类已被 Java 8 及更高版本中内置的 java.time 框架所取代。

如果您只想以 UTC 为单位显示当前时间,请使用该类。Instant

Instant now = Instant.now();

EST不是时区,正如Jon Skeet的正确答案中所解释的那样。这种3-4个字母的代码既不标准化也不唯一,并且进一步混淆了夏令时(DST)。使用“大洲/地区”格式的正确时区名称。

也许你的意思是北美东海岸的东部标准时间?还是埃及标准时间?还是欧洲标准时间?

ZoneId zoneId = ZoneId.of( "America/New_York" );
ZoneId zoneId = ZoneId.of( "Africa/Cairo" );
ZoneId zoneId = ZoneId.of( "Europe/Lisbon" );

使用任何此类对象将当前时刻调整为特定时区,以生成 ZonedDateTime 对象。ZoneId

ZonedDateTime zdt = ZonedDateTime.now( zoneId ) ;

通过将 ZonedDateTime 调整为不同的时区,方法是从第一个对象生成另一个 ZonedDateTime 对象。java.time 框架使用不可变对象,而不是更改(改变)现有对象。

ZonedDateTime zdtGuam = zdt.withZoneSameInstant( ZoneId.of( "Pacific/Guam" ) ) ;

Java 中的日期时间类型表,包括现代和旧版。