为什么 java 8 时间没有显示时区 Etc/GMT+1 的正确时间

Why is java 8 time not showing me the correct time for timezone Etc/GMT+1

ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Etc/GMT+1"));

调试时的这个值显示 2019-07-02T14:23:57.463-01:00[Etc/GMT+1]

应该是 16:23,我错过了什么.. 时钟不知为何慢了 2 小时?

tl;博士

使用时区而不仅仅是偏移量。

ZonedDateTime.now( 
    ZoneId.of( "Europe/Dublin" )
)

详情

在现代协议中,偏移量中 hours-minutes-seconds 的数量被认为是正数,比基线 (GMT/UTC) 提前 ,而负数数字 落后于 基线。一些较旧的协议是相反的。你的Etc/GMT+1好像是反的风格。

最好的解决方案是使用时区而不是仅仅偏移。偏移量只是 hours-minutes-seconds 的数字。时区 。时区是特定地区人们使用的偏移量的过去、现在和未来变化的历史。

时区的名称格式为 Continent/Region。例如,America/MontrealEurope/ParisPacific/Auckland

ZoneId z = ZoneId.of( "Europe/Dublin" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

生成标准 ISO 8601 格式的字符串,明智地扩展以在方括号中附加区域名称。

String output = zdt.toString() ;

您的大部分业务逻辑、日志记录和数据更改都应使用 UTC。要调整为 UTC,请从您的 ZonedDateTime 中提取一个 Instant。同一时刻,时间轴上的同一点,但 wall-clock 时间不同。

Instant instant = zdt.toInstant() ;

生成标准 ISO 8601 格式的字符串。

String output = instant.toString() ;

你的例子

所以现在我们可以回去检查您的具体情况。

让我们用 [Etc/GMT+1] 作为区域名称来解析给定的字符串。

String input = "2019-07-02T14:23:57.463-01:00[Etc/GMT+1]" ;
ZonedDateTime zdtInput = ZonedDateTime.parse ( input );

然后调整为UTC。

Instant instant = zdtInput.toInstant ();

再次调整为Europe/Dublin.

ZoneId zDublin = ZoneId.of( "Europe/Dublin");
ZonedDateTime zdtDublin = zdtInput.withZoneSameInstant ( zDublin );

转储到控制台。

System.out.println ("zdtInput: " + zdtInput );
System.out.println ("instant: " + instant );
System.out.println ("zdtDublin: " + zdtDublin );

看到这个code run live at IdeOne.com

zdtInput: 2019-07-02T14:23:57.463-01:00[Etc/GMT+1]

instant: 2019-07-02T15:23:57.463Z

zdtDublin: 2019-07-02T16:23:57.463+01:00[Europe/Dublin]

14 小时

果然,我们看到 day-of-time 和 [Etc/GMT+1] 落后 UTC(小时偏移的旧反向含义)一个小时14.

15 小时

UTC(偏移量为零 hours-minutes-seconds)有一个小时 15

16 小时

那一刻的Dublin time zone is using Irish Standard Time (IST), UTC +1 rather than Daylight Saving Time (DST)。所以我们看到它的时间是 16,比 UTC 15 小时 提前 小时。

关键: 了解所有这三个代表同一时刻,时间轴上的同一点。他们的 wall-clock 时间不同:查看同一时刻的三种方式。


顺便说一句,如果您想专门使用偏移量而不是时区,请使用 OffsetDateTime & ZoneOffset 类。 ZonedDateTime & ZoneId 类 用于时区。