ZonedDateTime比较异常:Etc/UTC与UTC时区判定不等问题问询
问题解析:Etc/UTC与UTC的ZonedDateTime比较问题
这确实是JDK的设计行为,而非你的使用错误,你提交的Bug(JDK-8196398)也准确反映了这个反直觉的点——很多开发者都会默认时区规则一致就应该被视为等价,但JDK的实现逻辑并非如此。
核心原因拆解
ZonedDateTime的相等性逻辑
ZonedDateTime的equals()和compareTo()方法会同时校验两个维度:- 底层的时间点(Instant)
- 关联的ZoneId的精确身份
而ZoneId的相等性是基于其ID字符串的完全匹配,不是时区的实际偏移规则。ZoneId.of("Etc/UTC")和ZoneId.of("UTC")虽然时区规则完全一致(都是UTC偏移),但ID字符串不同,所以ZoneId实例不相等,进而导致ZonedDateTime的比较失败。
UTC与UTC+0能匹配的特殊原因
你测试的UTC+0是个特殊情况:ZoneId.of("UTC")返回的是ZoneRegion类型,代表一个时区区域,ID为"UTC"ZoneId.of("UTC+0")会被解析为ZoneOffset类型,代表固定的+00:00偏移量
当ZonedDateTime比较时,如果其中一方关联的是ZoneOffset,逻辑会变为:先比较时间点(Instant),再比较偏移量的数值,而不是ZoneId的ID字符串。因为UTC的ZoneRegion对应的偏移量也是+00:00,所以二者能通过所有断言。
可行的解决方案
如果你需要判断两个ZonedDateTime是否代表同一个时间点(忽略时区ID的差异),可以采用以下方式:
- 直接比较它们的
toInstant()结果(就像你第一个通过的断言那样):assertEquals(zoneDateTimeEtcUtc.toInstant(), zoneDateTimeUtc.toInstant()); - 或者同时比较时间戳和偏移量:
assertEquals(zoneDateTimeEtcUtc.toEpochSecond(), zoneDateTimeUtc.toEpochSecond()); assertEquals(zoneDateTimeEtcUtc.getOffset(), zoneDateTimeUtc.getOffset()); - 如果需要统一时区ID来满足严格的ZonedDateTime相等,可以手动将所有时区转换为统一的ID,比如都使用
ZoneId.of("UTC")。
内容的提问来源于stack exchange,提问作者Andremoniy
相关产品推荐
相关产品推荐

