首页 > 解决方案 > 为什么 java 8 时间没有向我显示时区 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 小时?

标签: javajava-8timestampjava-time

解决方案


tl;博士

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

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

细节

在现代协议中,偏移中的小时-分钟-秒数被视为高于基线 (GMT/UTC) 的正数,而负数被视为落后于基线。一些较旧的协议则相反。你Etc/GMT+1的风格似乎是相反的。

最好的解决方案是使用时区而不是仅仅使用偏移量。偏移量只是几个小时-分钟-秒。时区更多。时区是特定地区的人们使用的偏移量的过去、现在和未来变化的历史。

时区的名称格式为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,Instant请从ZonedDateTime. 同一时刻,时间轴上的同一点,但挂钟时间不同。

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 );

请参阅在 IdeOne.com 上实时运行的代码

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

瞬间:2019-07-02T15:23:57.463Z

zdt都柏林:2019-07-02T16:23:57.463+01:00[欧洲/都柏林]

14 小时

果然,我们看到时间比 UTC[Etc/GMT+1]一个小时(小时偏移的旧反向含义)一个小时。14

15 小时

UTC(零时分秒的偏移量)有一小时15.

16 小时

都柏林时区当时使用的是爱尔兰标准时间 (IST),UTC +1 而不是夏令时 (DST)。所以我们看到它的时间是16UTC 的时间早一个15小时。

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


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


推荐阅读