¿Por qué ZoneOffset.UTC! = ZoneId.of (“UTC”)?


125

Por que

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

imprimir false?

Esperaría que ambas ZonedDateTimeinstancias fueran iguales.

Respuestas:


180

La respuesta viene del javadoc deZoneId (énfasis mío) ...

Un ZoneId se usa para identificar las reglas que se usan para convertir entre Instant y LocalDateTime. Hay dos tipos distintos de identificación:

  • Desplazamientos fijos: un desplazamiento completamente resuelto de UTC / Greenwich, que utiliza el mismo desplazamiento para todas las fechas y horas locales
  • Regiones geográficas: un área donde se aplica un conjunto específico de reglas para encontrar el desplazamiento de UTC / Greenwich

La mayoría de las compensaciones fijas están representadas por ZoneOffset. Llamar a normalized () en cualquier ZoneId garantizará que un ID de desplazamiento fijo se represente como ZoneOffset.

... y del javadoc deZoneId#of (énfasis mío):

Este método analiza el ID que produce un ZoneId o ZoneOffset. Se devuelve un ZoneOffset si el ID es 'Z' o comienza con '+' o '-' .

El id del argumento se especifica como "UTC", por lo tanto, devolverá un ZoneIdcon un desplazamiento, que también se presenta en forma de cadena:

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

Salidas:

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

A medida que utiliza el equalsmétodo de comparación, comprueba la equivalencia de objetos . Debido a la diferencia descrita, el resultado de la evaluación es false.

Cuando normalized()se utilice el método propuesto en la documentación, equalsse devolverá la comparación utilizando true, ya normalized()que devolverá el correspondiente ZoneOffset:

Normaliza el ID de la zona horaria, devolviendo un ZoneOffset siempre que sea posible.

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

Como indica la documentación, si usa "Z"o "+0"como ID de entrada, ofdevolverá el ZoneOffsetdirectamente y no es necesario llamar normalized():

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

Para verificar si almacenan la misma fecha y hora , puede usar el isEqualmétodo en su lugar:

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

Muestra

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

Salida:

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
Los documentos también dicen "Si el ID de zona es igual a 'GMT', 'UTC' o 'UT', el resultado es un ZoneId con el mismo ID y reglas equivalentes a ZoneOffset.UTC". Misma identificación y reglas, pero comportamiento diferente. ZoneId.of("Z")te da ZoneOffset.UTCpero te ZoneId.of("UTC")da un ZoneId(que no es ZoneOffset.UTC). Esta API no es intuitiva, por decir lo menos.
Adam Millerchip
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.