tl;博士
使用时区而不是单纯的偏移量。
ZonedDateTime.now(
ZoneId.of( "Europe/Dublin" )
)
详情
在现代协议中,偏移量中的小时-分钟-秒数被视为在基线 (GMT/UTC) 之前 的正数,而在之后 被视为负数 基线。一些较旧的协议则相反。你的Etc/GMT+1 好像是反风格的。
最好的解决方案是使用时区,而不是仅仅使用偏移量。偏移量只是几个小时-分钟-秒。时区更多。时区是特定地区的人们使用的偏移量的过去、现在和未来变化的历史。
时区的名称格式为Continent/Region。例如,America/Montreal、Europe/Paris 和 Pacific/Auckland。
ZoneId z = ZoneId.of( "Europe/Dublin" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
生成标准 ISO 8601 格式的字符串,明智地扩展以将区域名称附加在方括号中。
String output = zdt.toString() ;
您的大部分业务逻辑、日志记录和数据更改都应该使用 UTC。要适应 UTC,请从您的 ZonedDateTime 中提取 Instant。同一时刻,时间轴上的同一点,但挂钟时间不同。
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。
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 小时
果然,我们看到[Etc/GMT+1] 的日期比世界标准时间落后一小时(小时偏移的旧反向含义)和14 的一小时。
15 小时
UTC(零时分秒的偏移量)有一小时为15。
16 小时
当时Dublin time zone 使用的是爱尔兰标准时间 (IST),UTC +1 而不是 Daylight Saving Time (DST)。所以我们在16 看到它的小时,比UTC 的15 小时提前一个小时。
至关重要:了解所有这三个都代表同一个时刻,时间轴上的同一个点。他们的挂钟时间不同:查看同一时刻的三种方式。
顺便说一句,当您想专门使用偏移量而不是时区时,请使用 OffsetDateTime 和 ZoneOffset 类。 ZonedDateTime 和 ZoneId 类用于时区。