ทำไม ZoneOffset.UTC! = ZoneId.of (“ UTC”)


126

ทำไม

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

พิมพ์ออกมาfalse?

ฉันคาดหวังว่าทั้งสองZonedDateTimeอินสแตนซ์จะเท่ากัน

คำตอบ:


181

คำตอบมาจากjavadoc ของZoneId (เน้นของฉัน) ...

ZoneId ใช้เพื่อระบุกฎที่ใช้ในการแปลงระหว่าง Instant และ LocalDateTime ID มีสองประเภทที่แตกต่างกัน:

  • ออฟเซ็ตคงที่ - ออฟเซ็ตที่ได้รับการแก้ไขอย่างสมบูรณ์จาก UTC / Greenwich ซึ่งใช้ออฟเซ็ตเดียวกันสำหรับวันที่ - เวลาท้องถิ่นทั้งหมด
  • ภูมิภาคทางภูมิศาสตร์ - พื้นที่ที่ใช้ชุดกฎเฉพาะสำหรับการหาค่าชดเชยจาก UTC / Greenwich

ออฟเซ็ตคงที่ส่วนใหญ่แสดงโดย ZoneOffset การเรียก normalized () บน ZoneId ใด ๆ จะทำให้แน่ใจว่า ID ออฟเซ็ตคงที่จะแสดงเป็น ZoneOffset

... และจากjavadoc ของZoneId#of (เน้นของฉัน):

วิธีนี้จะแยกวิเคราะห์ ID ที่สร้าง ZoneId หรือ ZoneOffset ZoneOffset ถูกส่งกลับถ้า ID คือ 'Z' หรือเริ่มต้นด้วย '+' หรือ '-'

รหัสอาร์กิวเมนต์ถูกระบุเป็น"UTC"ดังนั้นมันจะส่งคืน a 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:

ปรับรหัสโซนเวลาให้เป็นปกติโดยส่งคืน ZoneOffset หากเป็นไปได้

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

ตามที่ระบุในเอกสารหากคุณใช้"Z"หรือ"+0"เป็นรหัสอินพุต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

4
เอกสารยังระบุว่า "ถ้ารหัสโซนเท่ากับ 'GMT', 'UTC' หรือ 'UT' ผลลัพธ์จะเป็น ZoneId ที่มี ID เดียวกันและกฎที่เทียบเท่ากับ ZoneOffset.UTC" รหัสและกฎเดียวกัน แต่พฤติกรรมต่างกัน ZoneId.of("Z")ให้คุณZoneOffset.UTCแต่ZoneId.of("UTC")ให้ZoneId(นั่นไม่ใช่ZoneOffset.UTC) API นี้ไม่ใช้งานง่ายพูดน้อยที่สุด
Adam Millerchip
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.