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

后端 未结 1 1496
逝去的感伤
逝去的感伤 2021-01-29 23:01

Why does

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


        
相关标签:
1条回答
  • 2021-01-29 23:38

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

    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.

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

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

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

    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 equals method for comparison, you check for object equivalence. Because of the described difference, the result of the evaluation is false.

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

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

    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, of will return the ZoneOffset directly and there is no need to call 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 isEqual method instead:

    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
    
    0 讨论(0)
提交回复
热议问题