【问题标题】:What is the difference between ZoneOffset.UTC and ZoneId.of("UTC")?ZoneOffset.UTC 和 ZoneId.of("UTC") 有什么区别?
【发布时间】:2017-01-23 05:32:32
【问题描述】:

为什么

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

打印出false?

我希望两个 ZonedDateTime 实例相等。

【问题讨论】:

标签: java datetime java-8 java-time


【解决方案1】:

答案来自javadoc of ZoneId(重点是我的)...

ZoneId 用于标识用于在 Instant 和 LocalDateTime。有两种不同类型的 ID:

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

大多数固定偏移由 ZoneOffset 表示。 调用 normalized() 在任何 ZoneId 上将确保将表示一个固定的偏移 ID 作为 ZoneOffset。

...来自javadoc of ZoneId#of(强调我的):

此方法解析生成 ZoneId 或 ZoneOffset 的 ID。 一个 如果 ID 为“Z”或以“+”或“-”开头,则返回 ZoneOffset。

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

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

输出:

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

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

当按照文档中的建议使用normalized() 方法时,使用equals 的比较将返回true,因为normalized() 将返回对应的ZoneOffset

规范化时区 ID,尽可能返回 ZoneOffset。

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

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

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

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

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

示例

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"))));

输出:

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

【讨论】:

  • 文档还说“如果区域 ID 等于 'GMT'、'UTC' 或 'UT',则结果是具有相同 ID 和规则的 ZoneId 等效于 ZoneOffset.UTC”。相同的 ID 和规则,但不同的行为。 ZoneId.of("Z") 给你ZoneOffset.UTCZoneId.of("UTC") 给你一个ZoneId(那不是ZoneOffset.UTC)。至少可以说,这个 API 不直观。
  • ...API 是灾难。
猜你喜欢
  • 2021-12-26
  • 2013-02-03
  • 2018-02-11
  • 2018-04-22
  • 2012-12-17
  • 1970-01-01
  • 2010-10-02
  • 2011-12-12
  • 2010-09-16
相关资源
最近更新 更多