Почему
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now.withZoneSameInstant(ZoneOffset.UTC)
.equals(now.withZoneSameInstant(ZoneId.of("UTC"))));
распечатать false
?
Я ожидал, что оба ZonedDateTime
экземпляра будут равны.
Ответ исходит из javadocZoneId
(выделено мной) ...
ZoneId используется для идентификации правил, используемых для преобразования между Instant и LocalDateTime. Есть два различных типа идентификаторов:
- Фиксированные смещения - полностью разрешенное смещение от UTC / Гринвича, которое использует то же смещение для всех локальных дат и времени.
- Географические регионы - регион, в котором применяется определенный набор правил для определения смещения от UTC / Гринвича.
Большинство фиксированных смещений представлено ZoneOffset. Вызов normalized () для любого ZoneId гарантирует, что фиксированный идентификатор смещения будет представлен как ZoneOffset.
... и из javadocZoneId#of
(выделено мной):
Этот метод анализирует идентификатор, создавая ZoneId или ZoneOffset. ZoneOffset возвращается, если идентификатор равен «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
ZoneId.of("Z")
дает вам,ZoneOffset.UTC
ноZoneId.of("UTC")
дает вамZoneId
(это не такZoneOffset.UTC
). Этот API, мягко говоря, не интуитивно понятен.