Java 为什么是 ZoneOffset.UTC != ZoneId.of("UTC")?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39506891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:12:30  来源:igfitidea点击:

Why is ZoneOffset.UTC != ZoneId.of("UTC")?

javadatetimejava-8java-time

提问by Johannes Flügel

Why does

为什么

ZonedDateTime now = ZonedDateTime.now();
System.out.println(now.withZoneSameInstant(ZoneOffset.UTC)
        .equals(now.withZoneSameInstant(ZoneId.of("UTC"))));

print out false?

打印出来false

I would expect the both ZonedDateTimeinstances to be equal.

我希望这两个ZonedDateTime实例是平等的。

采纳答案by DVarga

The answer comes from the javadoc of ZoneId(emphasis mine) ...

答案来自(强调我的)的javadocZoneId...

A ZoneId is used to identify the rules used to convert between an Instant and a LocalDateTime. There are two distinct types of ID:

  • Fixed offsets - a fully resolved offset from UTC/Greenwich, that uses the same offset for all local date-times
  • Geographical regions - an area where a specific set of rules for finding the offset from UTC/Greenwich apply

Most fixed offsets are represented by ZoneOffset. Calling normalized() on any ZoneId will ensure that a fixed offset ID will be represented as a ZoneOffset.

ZoneId 用于标识用于在 Instant 和 LocalDateTime 之间转换的规则。有两种不同类型的 ID:

  • 固定偏移量 - UTC/格林威治的完全解析偏移量,对所有本地日期时间使用相同的偏移量
  • 地理区域 - 应用一组特定规则来查找 UTC/格林威治偏移量的区域

大多数固定偏移量由 ZoneOffset 表示。对任何 ZoneId 调用 normalized() 将确保固定偏移 ID 将表示为 ZoneOffset。

... and from the javadoc of ZoneId#of(emphasis mine):

...以及来自(强调我的)的javadocZoneId#of

This method parses the ID producing a ZoneId or ZoneOffset. A ZoneOffset is returned if the ID is 'Z', or starts with '+' or '-'.

此方法解析 ID 生成 ZoneId 或 ZoneOffset。如果 ID 为 'Z',或者以 '+' 或 '-' 开头,则返回 ZoneOffset

The argument id is specified as "UTC", therefore it will return a ZoneIdwith an offset, which also presented in the string form:

参数 id 被指定为"UTC",因此它将返回ZoneId带有偏移量的 a ,它也以字符串形式呈现:

System.out.println(now.withZoneSameInstant(ZoneOffset.UTC));
System.out.println(now.withZoneSameInstant(ZoneId.of("UTC")));

Outputs:

输出:

2017-03-10T08:06:28.045Z
2017-03-10T08:06:28.045Z[UTC]

As you use the equalsmethod for comparison, you check for object equivalence. Because of the described difference, the result of the evaluation is false.

当您使用该equals方法进行比较时,您会检查对象等效性。由于所描述的差异,评估结果为false

When the normalized()method is used as proposed in the documentation, the comparison using equalswill return true, as normalized()will return the corresponding ZoneOffset:

当按照normalized()文档中的建议使用该方法时,比较 usingequals将返回truenormalized()并将返回相应的ZoneOffset

Normalizes the time-zone ID, returning a ZoneOffset where possible.

标准化时区 ID,在可能的情况下返回 ZoneOffset。

now.withZoneSameInstant(ZoneOffset.UTC)
    .equals(now.withZoneSameInstant(ZoneId.of("UTC").normalized())); // true

As the documentation states, if you use "Z"or "+0"as input id, ofwill return the ZoneOffsetdirectly and there is no need to call normalized():

正如文档所述,如果您使用"Z""+0"作为输入 id,ofZoneOffset直接返回 ,无需调用normalized()

now.withZoneSameInstant(ZoneOffset.UTC).equals(now.withZoneSameInstant(ZoneId.of("Z"))); //true
now.withZoneSameInstant(ZoneOffset.UTC).equals(now.withZoneSameInstant(ZoneId.of("+0"))); //true


To check if they store the same date time, you can use the isEqualmethod instead:

要检查它们是否存储相同的日期时间,您可以改用该isEqual方法:

now.withZoneSameInstant(ZoneOffset.UTC)
    .isEqual(now.withZoneSameInstant(ZoneId.of("UTC"))); // true


Sample

样本

System.out.println("equals - ZoneId.of(\"UTC\"): " + nowZoneOffset
        .equals(now.withZoneSameInstant(ZoneId.of("UTC"))));
System.out.println("equals - ZoneId.of(\"UTC\").normalized(): " + nowZoneOffset
        .equals(now.withZoneSameInstant(ZoneId.of("UTC").normalized())));
System.out.println("equals - ZoneId.of(\"Z\"): " + nowZoneOffset
        .equals(now.withZoneSameInstant(ZoneId.of("Z"))));
System.out.println("equals - ZoneId.of(\"+0\"): " + nowZoneOffset
        .equals(now.withZoneSameInstant(ZoneId.of("+0"))));
System.out.println("isEqual - ZoneId.of(\"UTC\"): "+ nowZoneOffset
        .isEqual(now.withZoneSameInstant(ZoneId.of("UTC"))));

Output:

输出:

equals - ZoneId.of("UTC"): false
equals - ZoneId.of("UTC").normalized(): true
equals - ZoneId.of("Z"): true
equals - ZoneId.of("+0"): true
isEqual - ZoneId.of("UTC"): true