Scala中GMT与BST时区的ZonedDateTime转Instant后为何值相同?
问题:GMT与BST时区的ZonedDateTime转换Instant后值相同的疑惑
我遇到一个问题:拥有两个本地时间相同但时区分别为GMT和BST的ZonedDateTime对象,调用toInstant转换后得到了相同的Instant值。我原本预期转换后它们的值应该不同,因为这两个时间字符串代表不同时区的同一本地时间,不确定是库的bug还是自身代码问题。
复现代码(Scala)
import ... import java.util.{Set => JavaSet} val string2 = "Tue Feb 23 18:00:46 BST 2021" val string1 = "Tue Feb 23 18:00:46 GMT 2021" val timestampFormat: DateTimeFormatter = new DateTimeFormatterBuilder() .appendOptional(DateTimeFormatter.ISO_DATE_TIME) .appendOptional(DateTimeFormatter.ISO_INSTANT) .appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME) .appendOptional(DateTimeFormatter.ISO_ZONED_DATE_TIME) .appendOptional(DateTimeFormatter.RFC_1123_DATE_TIME) .appendPattern("EEE MMM ppd HH:mm:ss ") .appendZoneText(TextStyle.SHORT, JavaSet.of(ZoneId.of("Europe/London"))) .appendPattern(" yyyy") .toFormatter(Locale.US) val parsedZdt2: ZonedDateTime = ZonedDateTime.parse(string2, timestampFormat) val parsedZdt1: ZonedDateTime = ZonedDateTime.parse(string1, timestampFormat) println(parsedZdt1 == parsedZdt2) println("parsedZdt1.toString: " + parsedZdt1.toString) println("parsedZdt2.toString: " + parsedZdt2.toString)
代码执行输出
false parsedZdt1.toString: 2021-02-23T18:00:46Z[GMT] parsedZdt2.toString: 2021-02-23T18:00:46Z[Europe/London]
转换为Instant的代码与输出
代码
println(parsedZdt1.toInstant == parsedZdt2.toInstant) println("parsedZdt1.toInstant.toString: " + parsedZdt1.toInstant.toString) println("parsedZdt2.toInstant.toString: " + parsedZdt2.toInstant.toString)
输出
true parsedZdt1.toInstant.toString: 2021-02-23T18:00:46Z parsedZdt2.toInstant.toString: 2021-02-23T18:00:46Z
问题解答
1. 为何两个ZonedDateTime转换为Instant后值相同?
核心原因是2021年2月23日属于英国冬令时时段,此时欧洲/伦敦时区的实际偏移量与GMT一致(均为UTC+0)。
你的代码通过appendZoneText限制了解析时区只能是Europe/London,所以解析"BST"时,因为当前日期不在夏令时范围内,系统会自动将其映射为Europe/London时区的UTC+0偏移;而解析"GMT"时,直接对应UTC+0的时区偏移。
两个ZonedDateTime的本地时间相同,且UTC偏移量完全一致,转换为代表UTC时间线上固定点的Instant时,自然会得到同一个值。
2. 转换前的parsedZdt1和parsedZdt2是否代表同一时刻?
是的,它们代表完全相同的时刻。
虽然parsedZdt1的时区ID是GMT,parsedZdt2是Europe/London,但在2021年2月23日这个时间点,两个时区的实际偏移量都是UTC+0,结合相同的本地时间,对应的UTC时间(即Instant)完全一致。
至于parsedZdt1 == parsedZdt2返回false,是因为ZonedDateTime的equals方法会同时校验时区ID,GMT和Europe/London是不同的时区标识,所以对象本身不相等,但它们对应的实际时间点毫无差异。
内容的提问来源于stack exchange,提问作者Adrian Qin
相关产品推荐
相关产品推荐

