我正在比较两个似乎相等的日期,但它们包含不同的区域名称:一个是Etc/UTC
,另一个是UTC
。
根据这个问题:UTC 和 Etc/UTC 时区之间有区别吗?- 这两个区域是相同的。但是我的测试失败了:
import org.junit.Test;
import java.sql.Timestamp;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import static org.junit.Assert.assertEquals;
public class TestZoneDateTime {
@Test
public void compareEtcUtcWithUtc() {
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime zoneDateTimeEtcUtc = now.withZoneSameInstant(ZoneId.of("Etc/UTC"));
ZonedDateTime zoneDateTimeUtc = now.withZoneSameInstant(ZoneId.of("UTC"));
// This is okay
assertEquals(Timestamp.from(zoneDateTimeEtcUtc.toInstant()), Timestamp.from(zoneDateTimeUtc.toInstant()));
// This one fails
assertEquals(zoneDateTimeEtcUtc,zoneDateTimeUtc);
// This fails as well (of course previous line should be commented!)
assertEquals(0, zoneDateTimeEtcUtc.compareTo(zoneDateTimeUtc));
}
}
结果:
java.lang.AssertionError:
Expected :2018-01-26T13:55:57.087Z[Etc/UTC]
Actual :2018-01-26T13:55:57.087Z[UTC]
更具体地说,我希望这ZoneId.of("UTC")
等于ZoneId.of("Etc/UTC")
,但事实并非如此!
正如@NicolasHenneaux建议的那样,我可能应该使用compareTo(...)
方法。这是个好主意,但zoneDateTimeEtcUtc.compareTo(zoneDateTimeUtc)
返回-16
值,因为内部的这个实现ZoneDateTime
:
cmp = getZone().getId().compareTo(other.getZone().getId());
断言结果:
java.lang.AssertionError:
Expected :0
Actual :-16
ZoneId
所以问题出在实施的某个地方。但我仍然希望,如果两个区域 id 都有效并且都指定同一个区域,那么它们应该是相等的。
我的问题是:这是一个库错误,还是我做错了什么?
更新
有几个人试图说服我这是一种正常行为,比较方法的实现String
使用ZoneId
. 在这种情况下,我应该问,为什么以下测试运行正常?
@Test
public void compareUtc0WithUtc() {
ZonedDateTime now = ZonedDateTime.now();
ZoneId utcZone = ZoneId.of("UTC");
ZonedDateTime zonedDateTimeUtc = now.withZoneSameInstant(utcZone);
ZoneId utc0Zone = ZoneId.of("UTC+0");
ZonedDateTime zonedDateTimeUtc0 = now.withZoneSameInstant(utc0Zone);
// This is okay
assertEquals(Timestamp.from(zonedDateTimeUtc.toInstant()), Timestamp.from(zonedDateTimeUtc0.toInstant()));
assertEquals(0, zonedDateTimeUtc.compareTo(zonedDateTimeUtc0));
assertEquals(zonedDateTimeUtc,zonedDateTimeUtc0);
}
如果Etc/UTC
与相同UTC
,那么我看到两个选项:
- compareTo/equals 方法不应使用 ZoneId id,而应比较它们的规则
Zone.of(...)
已损坏,应将Etc/UTC
和UTC
视为相同的时区。
否则我不明白为什么UTC+0
并且UTC
工作正常。
UPDATE-2我报告了一个错误,ID:9052414。看看 Oracle 团队会做出什么决定。
UPDATE-3接受的错误报告(不知道他们是否会将其关闭为“无法修复”):https ://bugs.openjdk.java.net/browse/JDK-8196398