Сравнение дат в Java: проверка совпадения дня, месяца, года

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Java
Скопировать код
boolean sameDay = DateUtils.isSameDay(date1, date2);

С помощью метода isSameDay из Apache Commons Lang's DateUtils можно быстро и надежно проверить, принадлежат ли два объекта типа Date одному календарному дню. Этот вариант будет полезен для тех, кто ценит скорость и консистентность.

Впрочем, если вас не пугают некоторые сложности, то читайте дальше!

Кинга Идем в IT: пошаговый план для смены профессии

Осторожно: разница во времени

Одной из основных проблем при сравнении дат являются различия во времени. Ваш календарь уже может показывать новый день, когда у вашего друга на другой стороне планеты еще продолжается вчерашнее утро. Если эти расхождения волнуют вас, помочь может следующий код:

Java
Скопировать код
Calendar cal1 = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal1.setTime(date1);
Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal2.setTime(date2);
boolean sameDay = (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
                   cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
                   cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));

Данный код конвертирует обе даты в UTC, при этом исключая все возможности для «споров из-за времени». Все честно и прозрачно.

Средневековый метод для исключительных случаев

Иногда может быть полезно обратиться к проверенным методам. С помощью SimpleDateFormat мы можем отформатировать даты в строгий формат "yyyyMMdd", просто игнорируя временную составляющую ваших объектов Date. При этом получится чисто и без излишеств.

Давайте воспользуемся историческим примером и подсчитаем юлианский день — метод отсчета дат, уходящий корнями в древность.

С появлением Java 8 упрощение этой задачи стало возможным благодаря классу LocalDate, который позволяет убрать время из дат:

Java
Скопировать код
LocalDate localDate1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate localDate2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
boolean sameDay = localDate1.isEqual(localDate2);

И теперь мы сравниваем только календарные даты, без учета времени.

Сравнение дат – подход "Полуоткрытый интервал"

Есть ещё один способ. Давайте применим стратегию "Полуоткрытый интервал", которая проверяет, попадает ли date2 в интервал между началом и концом date1. Пример такого подхода:

Java
Скопировать код
Calendar startOfDay = Calendar.getInstance();
startOfDay.setTime(date1);
startOfDay.set(Calendar.HOUR_OF_DAY, 0);
startOfDay.set(Calendar.MINUTE, 0);
startOfDay.set(Calendar.SECOND, 0);
startOfDay.set(Calendar.MILLISECOND, 0);

Date start = startOfDay.getTime();
Date end = new Date(startOfDay.getTimeInMillis() + TimeUnit.DAYS.toMillis(1));

boolean sameDay = !date2.before(start) && date2.before(end);

Этот метод учитывает разницу во времени на уровне миллисекунд.

Управление разницей во времени с помощью java.time

Класс java.time.ZonedDateTime отлично справляется с трудностями, связанными с часовыми поясами:

Java
Скопировать код
ZonedDateTime zonedDate1 = date1.toInstant().atZone(ZoneId.systemDefault());
ZonedDateTime zonedDate2 = date2.toInstant().atZone(ZoneId.systemDefault());
boolean sameDay = zonedDate1.toLocalDate().isEqual(zonedDate2.toLocalDate());

Этот код делает сравнение дат по всем временным зонам простым и понятным.

Усложнённая запись в виде утилиты для повышения элегантности кода

Чтобы избежать постоянных повторов операций сравнения дат, используйте вспомогательные методы:

Java
Скопировать код
public static boolean isSameCalendarDay(Date date1, Date date2) {
    LocalDate localDate1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    LocalDate localDate2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    return localDate1.isEqual(localDate2); // эффективность на уровне лучших пылесосов!
}

Такой подход облегчает восприятие кода и представляет собой готовое решение для будущих задач.

Завершение

Помните, что мастерство приходит со временем и опытом. Продолжайте кодить и при этом не забывайте сохранять свою работу перед тем, как завершить её! Успехов в программировании!👩‍💻