我正在比较两个似乎相等的日期,但它们包含的区域名称不同:一个是Etc/UTC
,另一个是UTC
。
根据这个问题:Is there a difference between the UTC and Etc/UTC time zones?-这两个区域是相同的。但是我的测试失败了:
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 suggested,我可能应该使用
compareTo(...)
方法。那是个好主意,但是zoneDateTimeEtcUtc.compareTo(zoneDateTimeUtc)
返回-16
值,因为ZoneDateTime
内有此实现:cmp = getZone().getId().compareTo(other.getZone().getId());
断言结果:
java.lang.AssertionError:
Expected :0
Actual :-16
因此,问题出在
ZoneId
实现中。但是我仍然希望,如果两个区域ID均有效且都指定相同的区域,则它们应该相等。我的问题是:这是库错误,还是我做错了什么?
更新
几个人试图说服我这是正常的行为,比较方法的实现使用
String
的ZoneId
id表示形式是正常的。在这种情况下,我应该问,为什么以下测试可以正常进行? @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
相同,那么我看到两个选项:Zone.of(...)
损坏,应将Etc/UTC
和UTC
视为相同的时区。 否则我看不出为什么
UTC+0
和UTC
可以正常工作。UPDATE-2 我已经报告了一个ID为9052414的错误。将看到Oracle团队将决定什么。
UPDATE-3 已接受此错误报告(不知道他们是否会因为“无法修复”而将其关闭):https://bugs.openjdk.java.net/browse/JDK-8196398
最佳答案
您可以将ZonedDateTime
对象转换为Instant
,如其他答案/评论所述。ZonedDateTime::isEqual
或者,您可以使用 isEqual
method,它比较两个ZonedDateTime
实例是否对应于相同的Instant
:
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime zoneDateTimeEtcUtc = now.withZoneSameInstant(ZoneId.of("Etc/UTC"));
ZonedDateTime zoneDateTimeUtc = now.withZoneSameInstant(ZoneId.of("UTC"));
Assert.assertTrue(zoneDateTimeEtcUtc.isEqual(zoneDateTimeUtc));
关于java - ZonedDateTime比较: expected: [Etc/UTC] but was: [UTC],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48462758/