«1. Введение

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

Мы покажем, как это сделать до и после Java 8, так как после выпуска нового API времени в Java 8 все стало немного иначе.

2. До Java 8

До Java 8, не было прямого способа получить Date без времени, если только мы не использовали сторонние библиотеки, такие как Joda-time.

Это связано с тем, что класс Date в Java является представлением определенного момента времени, выраженного в миллисекундах. Следовательно, это делает невозможным игнорирование времени на Date.

В следующих разделах мы покажем некоторые общие обходные пути для решения этой проблемы.

2.1. Использование календаря

Один из самых распространенных способов получить дату без времени — использовать класс Calendar, чтобы установить время равным нулю. Делая это, мы получаем чистую дату со временем, установленным в начале дня.

Давайте посмотрим на это в коде:

public static Date getDateWithoutTimeUsingCalendar() {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    return calendar.getTime();
}

Если мы вызовем этот метод, мы получим такую ​​дату:

Sat Jun 23 00:00:00 CEST 2018

Как мы видим, он возвращает полную дату со временем, установленным на ноль, но мы не можем игнорировать время.

Кроме того, чтобы убедиться, что в возвращаемой дате не установлено время, мы можем создать следующий тест:

@Test
public void whenGettingDateWithoutTimeUsingCalendar_thenReturnDateWithoutTime() {
    Date dateWithoutTime = DateWithoutTime.getDateWithoutTimeUsingCalendar();

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(dateWithoutTime);
    int day = calendar.get(Calendar.DAY_OF_MONTH);

    calendar.setTimeInMillis(dateWithoutTime.getTime() + MILLISECONDS_PER_DAY - 1);
    assertEquals(day, calendar.get(Calendar.DAY_OF_MONTH));

    calendar.setTimeInMillis(dateWithoutTime.getTime() + MILLISECONDS_PER_DAY);
    assertNotEquals(day, calendar.get(Calendar.DAY_OF_MONTH));
}

Как мы видим, когда мы добавляем к дате миллисекунды дня минус один мы по-прежнему получаем тот же день, но когда мы добавляем полный день, мы получаем следующий день.

2.2. Использование средства форматирования

Другой способ сделать это — отформатировать дату в строку без времени, а затем преобразовать эту строку обратно в дату. Поскольку строка была отформатирована без указания времени, преобразованная дата будет иметь нулевое время.

Давайте реализуем его, чтобы увидеть, как он работает:

public static Date getDateWithoutTimeUsingFormat() 
  throws ParseException {
    SimpleDateFormat formatter = new SimpleDateFormat(
      "dd/MM/yyyy");
    return formatter.parse(formatter.format(new Date()));
}

Эта реализация возвращает то же самое, что и метод, показанный в предыдущем разделе:

Sat Jun 23 00:00:00 CEST 2018

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

3. Использование Java 8

С выпуском нового API времени в Java 8 появился более простой способ получить дату без времени. Одна из новых функций, которую принес этот новый API, заключается в том, что есть несколько классов для работы с датами со временем или без него или даже для работы только со временем.

Ради этой статьи мы сосредоточимся на классе LocalDate, который представляет именно то, что нам нужно, дату без времени.

Давайте посмотрим на этот пример:

public static LocalDate getLocalDate() {
    return LocalDate.now();
}

Этот метод возвращает объект LocalDate с таким представлением даты:

2018-06-23

Как мы видим, он возвращает только дату, время полностью игнорируется.

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

@Test
public void whenGettingLocalDate_thenReturnDateWithoutTime() {
    LocalDate localDate = DateWithoutTime.getLocalDate();

    long millisLocalDate = localDate
      .atStartOfDay()
      .toInstant(OffsetDateTime
        .now()
        .getOffset())
      .toEpochMilli();

    Calendar calendar = Calendar.getInstance();

    calendar.setTimeInMillis(
      millisLocalDate + MILLISECONDS_PER_DAY - 1);
    assertEquals(
      localDate.getDayOfMonth(), 
      calendar.get(Calendar.DAY_OF_MONTH));

    calendar.setTimeInMillis(millisLocalDate + MILLISECONDS_PER_DAY);
    assertNotEquals(
      localDate.getDayOfMonth(), 
      calendar.get(Calendar.DAY_OF_MONTH));
}

4. Заключение

В этой статье мы показали, как получить Date без времени в Java. Сначала мы показали, как это сделать до Java 8, а также с использованием Java 8.

Как мы могли видеть в примерах, реализованных в статье, использование Java 8 всегда должно быть предпочтительным вариантом, поскольку оно имеет конкретное представление для работы. с датами без времени.

Как всегда, полный исходный код примеров доступен на GitHub.