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

Pourquoi

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

imprimer false ?

Je m’attendrais à ce que les deux instances de ZonedDateTime soient égales.

La réponse vient du javadoc de ZoneId (emphase le mien) …

Un ZoneId est utilisé pour identifier les règles utilisées pour convertir entre Instant et LocalDateTime. Il existe deux types distincts d’ID:

  • Correction des décalages – un décalage entièrement résolu par rapport à UTC / Greenwich, qui utilise le même décalage pour toutes les dates et heures locales
  • Régions géographiques – une zone où un ensemble spécifique de règles pour trouver le décalage entre UTC / Greenwich s’applique

La plupart des décalages fixes sont représentés par ZoneOffset. L’appel de normalized () sur n’importe quel ZoneId garantira qu’un ID de décalage fixe sera représenté comme un ZoneOffset.

… et du javadoc de ZoneId#of (souligné par moi):

Cette méthode parsing l’ID produisant un ZoneId ou un ZoneOffset. Un ZoneOffset est renvoyé si l’ID est «Z» ou commence par «+» ou «-» .

L’argument id est spécifié comme "UTC" , il renverra donc un ZoneId avec un décalage, qui se présente également sous la forme de chaîne:

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

Les sorties:

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

Lorsque vous utilisez la méthode d’ equals pour la comparaison, vous vérifiez l’équivalence des objects . En raison de la différence décrite, le résultat de l’évaluation est false .

Lorsque la méthode normalized() est utilisée comme proposé dans la documentation, la comparaison utilisant les ZoneOffset retournera true , car normalized() retournera le ZoneOffset correspondant:

Normalise l’ID de fuseau horaire, renvoyant un ZoneOffset dans la mesure du possible.

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

Comme l’indique la documentation, si vous utilisez "Z" ou "+0" comme identifiant d’entrée, of ZoneOffset directement le ZoneOffset et il n’est pas nécessaire d’appeler normalized() :

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

Pour vérifier s’ils stockent la même heure , vous pouvez utiliser la méthode isEqual place:

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

Échantillon

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

Sortie:

 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 

Si vous les mettez tous les deux en Ssortingng, vous verrez que le premier est le 2016-09-15T09: 01: 13.816Z et le second est le 2016-09-15T09: 01: 13.816Z [UTC] ils sont en fait les mêmes mais le avec zoneID vous obtenez un [UTC] supplémentaire

EDIT: Vérifiez la réponse de @DVarga afin de l’obtenir comme vous le souhaitez