Как нормализовать ZonedDateTime, чтобы работало .equals()?

У меня есть код, похожий на этот:

import java.time._

object app {
  def main (args :Array[String]) = {
    println("app started")

    // create two ZonedDateTime objects for 1st Jan 2018, 10am UTC
    // using separate methods
    val zdt1 = ZonedDateTime.of(2018, 1, 1, 10, 0, 0, 0, ZoneId.of("UTC"))
    val zdt2 = ZonedDateTime.parse("2018-01-01T10:00:00Z")

    println(s"COMPARING: $zdt1 and $zdt2")
    println("== check:      " + (zdt1 == zdt2))
    println(".equals check: " + (zdt1.equals(zdt2)))
    println(".isEqual check " + (zdt1.isEqual(zdt2)))

    println("app finished")
  }
}

Код доступен здесь: https://ideone.com/43zf8B

Проблема:

  1. эти оба ЯВЛЯЮТСЯ типизированными объектами ZonedDateTime
  2. они эквивалентны в соответствии с методом .isEqual().
  3. они не эквивалентны согласно методу .equals()

Однако мой набор тестов использует глубокое сопоставление с использованием операций beEquals для классов, в которых находятся эти экземпляры datetime, поэтому мне нужен способ их нормализации, чтобы .equals() возвращал true.

как я могу их нормализовать, пожалуйста?


person Philluminati    schedule 22.01.2018    source источник
comment
Эпоха-нанос или Эпоха-миллис.   -  person sarveshseri    schedule 22.01.2018
comment
Какую библиотеку для тестирования вы используете?   -  person stefanobaghino    schedule 22.01.2018
comment
Совет: zdt.toInstant()   -  person Basil Bourque    schedule 22.01.2018
comment
Я только что провел рефакторинг набора тестов, чтобы построить ZonedDateTimes с использованием согласованного метода, поскольку это было менее трудоемко, чем попытка манипулировать глубоко вложенными экземплярами.   -  person Philluminati    schedule 23.01.2018


Ответы (2)


Если я создам zdt1 с ZonedDateTime.of(2018, 1, 1, 10, 0, 0, 0, ZoneOffset.UTC), два объекта равны под equals() (все еще не под == в Java).

Видимо, недостаточно, чтобы зоны были эквивалентны, когда их названия разные. При использовании ZoneOffset.UTC для построения первого ZonedDateTime оба будут иметь одинаковый часовой пояс и, таким образом, будут равны. С моим изменением, по крайней мере на моем Mac, zdt1.getZone() == zdt2.getZone() теперь оценивается как true.

В качестве более прямого ответа на ваш вопрос вы можете нормализовать свои объекты ZonedDateTime таким образом (синтаксис Java с точкой с запятой, пожалуйста, переведите сами):

    zdt1 = zdt1.withZoneSameInstant(zdt1.getZone().normalized());

Аналогично для zdt2, конечно. ZoneId.normalized() обещает вернуть ZoneOffset, где это возможно, как в вашем случае. Итак, в вашем случае это делает два объекта, которые равны под equals(). Я не уверен, что так будет во всех остальных случаях.

Более безопасным способом было бы, чтобы сравнение явно учитывало разные, но одинаковые часовые пояса:

zdt1.toInstant().equals(zdt2.toInstant())
        && zdt1.getZone().getRules().equals(zdt2.getZone().getRules())

Это оценивается как true с вашими двумя датами и временем из вопроса.

Кстати, isEqual() сравнивает только моменты времени, а не зоны вообще, поэтому ему все равно.

person Ole V.V.    schedule 22.01.2018

ZoneOffset.UTC

Как насчет предопределенной константы ZoneOffset.UTC ?

val zdt1 = ZonedDateTime.of(2018, 1, 1, 10, 0, 0, 0, ZoneOffset.UTC)
val zdt2 = ZonedDateTime.parse("2018-01-01T10:00:00Z")

Все три метода возвращают true(==, equals и isEqual)

person S.Karthik    schedule 22.01.2018