Perché ZoneOffset.UTC! = ZoneId.of ("UTC")?


125

Perché lo fa

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

stampare false?

Mi aspetto che entrambi i ZonedDateTimecasi siano uguali.

Risposte:


180

La risposta viene dal javadoc diZoneId (enfasi mia) ...

Uno ZoneId viene utilizzato per identificare le regole utilizzate per la conversione tra un Instant e un LocalDateTime. Esistono due tipi distinti di ID:

  • Offset fissi: un offset completamente risolto da UTC / Greenwich, che utilizza lo stesso offset per tutte le date-ora locali
  • Regioni geografiche: un'area in cui si applica una serie specifica di regole per trovare la differenza rispetto a UTC / Greenwich

La maggior parte degli offset fissi sono rappresentati da ZoneOffset. La chiamata normalized () su qualsiasi ZoneId assicurerà che un ID offset fisso sarà rappresentato come uno ZoneOffset.

... e dal javadoc diZoneId#of (enfasi mia):

Questo metodo analizza l'ID producendo uno ZoneId o uno ZoneOffset. Viene restituito uno ZoneOffset se l'ID è "Z" o inizia con "+" o "-" .

L'argomento id è specificato come "UTC", quindi restituirà a ZoneIdcon un offset, che si presenta anche sotto forma di stringa:

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

Uscite:

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

Mentre usi il equalsmetodo per il confronto, controlli l'equivalenza degli oggetti . A causa della differenza descritta, il risultato della valutazione è false.

Quando il normalized()metodo viene utilizzato come proposto nella documentazione, il confronto utilizzando equalsrestituirà true, così come normalized()restituirà il corrispondente ZoneOffset:

Normalizza l'ID del fuso orario, restituendo uno ZoneOffset ove possibile.

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

Come afferma la documentazione, se usi "Z"o "+0"come input id, ofrestituirà ZoneOffsetdirettamente e non è necessario chiamare normalized():

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

Per verificare se memorizzano la stessa data e ora , puoi utilizzare isEqualinvece il metodo:

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

Campione

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

Produzione:

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
I documenti dicono anche "Se l'ID zona è uguale a" GMT "," UTC "o" UT ", il risultato è uno ZoneId con lo stesso ID e regole equivalenti a ZoneOffset.UTC". Stessi ID e regole, ma comportamento diverso. ZoneId.of("Z")ti dà ZoneOffset.UTCma ti ZoneId.of("UTC")dà un ZoneId(che non è ZoneOffset.UTC). Questa API non è intuitiva, per non dire altro.
Adam Millerchip
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.