Как сравнить LocalDate с ZonedDateTime в js-joda?
Я ищу способ сравнить экземпляры LocalDate
а также ZonedDateTime
в js-joda
, но эти классы не совместимы. Я готов принять, что LocalDate
это ZonedDateTime
время и часовой пояс установлены на ноль.
Какой самый простой способ сравнить эти два объекта?
2 ответа
LocalDate
имеет только дату (день, месяц и год), а ZonedDateTime
также имеет время (часы, минуты, секунды и наносекунды) и часовой пояс. Чтобы сравнить их, вы должны выбрать, какой из них будет преобразован в тип другого.
Как уже объясняет ответ @Dummy, одним из способов является преобразование ZonedDateTime
к LocalDate
, Предположим, у нас есть:
var z = ZonedDateTime.now(); // 2017-08-23T13:12:24.856-03:00[America/Sao_Paulo]
var dt = LocalDate.now(); // 2017-08-23
Вы можете использовать методы equals
, isBefore
или же isAfter
проверить, совпадает ли местная дата (день / месяц / год) до или после другой
z.toLocalDate().equals(dt); // true
z.toLocalDate().isBefore(dt); // false
z.toLocalDate().isAfter(dt); // false
Вы также можете использовать compareTo
, который может вернуть -1
, 0
или же 1
если первая дата до, равна или после второй.
Как сказано в комментариях, звоню toLocalDate()
сбрасывает информацию о времени и часовом поясе, сохраняя только дату (день / месяц / год). Но как LocalDate
имеет только эти поля, другие не нужны для сравнения.
Чтобы сделать обратное (преобразовать LocalDate
к ZonedDateTime
), вам придется сделать некоторые предположения. Одна и та же дата может представлять разные моменты времени в зависимости от того, в каком часовом поясе вы находитесь (сейчас в Сан-Паулу 23 августа, а в Токио - 24 августа - выбранный вами часовой пояс может повлиять на конечный результат).
И вам также необходимо определить, в какое время (час / минута / секунда / наносекунда) будет указана эта дата. Вы сказали, что можете предположить, что LocalDate - это ZonedDateTime, для которого время и часовой пояс установлены в ноль. Это означает, что время будет полночь (00:00), а часовой пояс будет UTC (смещение нуля):
// consider LocalDate = ZonedDateTime with time and timezone set to zero (midnight in UTC)
var z2 = dt.atStartOfDay(ZoneOffset.UTC); // 2017-08-23T00:00Z
Тогда вы можете сравнить:
z2.equals(z); // false: check if all fields are the same (date/time/timezone)
z2.isEqual(z); // false: check if both represent the same instant (even if timezones are different)
z2.isBefore(z); // true
z2.isAfter(z); // false
z2.compareTo(z); // -1
Обратите внимание, что equals
проверяет, все ли поля одинаковы (дата, время и часовой пояс), а все остальные методы сравнивают эквивалентные Instant
(даже если часовые пояса разные, соответствующие Instant
используется для сравнения).
В этом случае, z2
является 2017-08-23T00:00Z
(23 августа 2017 года в полночь по UTC), а z
является 2017-08-23T13:12:24.856-03:00[America/Sao_Paulo]
, что эквивалентно в UTC 2017-08-23T16:12:24.856Z
(23 августа 2017 года в 16:12:24.856 по Гринвичу).
Так, equals
возвращается false
потому что время и часовой пояс разные и isEquals
возвращается false
потому что они не представляют одно и то же мгновение (даже при конвертации в UTC они разные). isBefore
возвращается true
так как z2
на самом деле раньше z
(полночь < 16:12) и так далее.
Если вы хотите использовать другой часовой пояс вместо UTC, вы должны использовать js-joda-timezone и ZoneId
учебный класс:
// get this date at midnight in London timezone
dt.atStartOfDay(ZoneId.of("Europe/London"));
API использует имена часовых поясов IANA (всегда в формате Region/City
, лайк America/Sao_Paulo
или же Europe/Berlin
). Избегайте использования трехбуквенных сокращений (например, CST
или же PST
) потому что они неоднозначны и не стандартны.
Вы можете получить список доступных часовых поясов (и выбрать тот, который лучше всего подходит вашей системе), позвонив ZoneId.getAvailableZoneIds()
,
Вы также можете использовать часовой пояс системы по умолчанию с ZoneId.systemDefault()
, но это будет зависеть от системы / браузера, поэтому лучше использовать конкретный.
Вы можете сделать это
zonedDateTime.toLocalDate().compareTo(otherLocalDate)
Который возвращается -1
если zonedDateTime
раньше otherLocalDate
, 1
после, 0
та же