Tại sao lại là ZoneOffset.UTC! = ZoneId.of (“UTC”)?


125

Tại sao

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

in ra false?

Tôi mong đợi cả hai ZonedDateTimetrường hợp bằng nhau.

Câu trả lời:


180

Câu trả lời đến từ javadoc củaZoneId (tôi nhấn mạnh) ...

ZoneId được sử dụng để xác định các quy tắc được sử dụng để chuyển đổi giữa Instant và LocalDateTime. Có hai loại ID riêng biệt:

  • Các khoảng chênh lệch cố định - phần bù được giải quyết đầy đủ từ UTC / Greenwich, sử dụng cùng một mức chênh lệch cho tất cả các ngày-giờ cục bộ
  • Khu vực địa lý - khu vực áp dụng một bộ quy tắc cụ thể để tìm mức chênh lệch từ UTC / Greenwich

Hầu hết các hiệu số cố định được đại diện bởi ZoneOffset. Gọi chuẩn hóa () trên bất kỳ ZoneId nào sẽ đảm bảo rằng một ID bù đắp cố định sẽ được biểu diễn dưới dạng ZoneOffset.

... và từ javadoc củaZoneId#of (tôi nhấn mạnh):

Phương thức này phân tích cú pháp ID tạo ra một ZoneId hoặc ZoneOffset. Một ZoneOffset được trả về nếu ID là 'Z' hoặc bắt đầu bằng '+' hoặc '-' .

Id đối số được chỉ định là "UTC", do đó nó sẽ trả về a ZoneIdvới một phần bù, cũng được trình bày ở dạng chuỗi:

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

Kết quả đầu ra:

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

Khi bạn sử dụng equalsphương pháp để so sánh, bạn kiểm tra tính tương đương của đối tượng . Vì sự khác biệt được mô tả, kết quả của việc đánh giá là false.

Khi normalized()phương thức được sử dụng như được đề xuất trong tài liệu, phép so sánh bằng cách sử dụng equalssẽ trả về true, cũng như normalized()sẽ trả về ZoneOffset:

Chuẩn hóa ID múi giờ, trả về ZoneOffset nếu có thể.

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

Như tài liệu nêu rõ, nếu bạn sử dụng "Z"hoặc "+0"làm id đầu vào, ofsẽ trả về ZoneOffsettrực tiếp và không cần gọi normalized():

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

Để kiểm tra xem chúng có lưu trữ cùng một ngày giờ hay không , bạn có thể sử dụng isEqualphương pháp thay thế:

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

Mẫu vật

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

Đầu ra:

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

4
Tài liệu cũng cho biết "Nếu ID vùng bằng 'GMT', 'UTC' hoặc 'UT' thì kết quả là ZoneId có cùng ID và quy tắc tương đương với ZoneOffset.UTC". Cùng một ID và quy tắc, nhưng hành vi khác nhau. ZoneId.of("Z")cho bạn ZoneOffset.UTCnhưng ZoneId.of("UTC")cho bạn một ZoneId(điều đó không phải ZoneOffset.UTC). API này không trực quan, để nói rằng ít nhất.
Adam Millerchip
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.