Разница между двумя датами в Java

Разница между двумя датами в Java

1. обзор

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

Дальнейшее чтение:

Дата приращения в Java

Обзор различных основных и сторонних методов для добавления дней к дате

Read more

Проверьте, является ли строка действительной датой в Java

Взгляните на разные способы проверить, является ли String действительной датой в Java

Read more

2. Основная Java

2.1. Использованиеjava.util.Date для определения разницы в днях

Давайте начнем с использования основных API-интерфейсов Java для расчета и определения количества дней между двумя датами:

@Test
public void givenTwoDatesBeforeJava8_whenDifferentiating_thenWeGetSix()
  throws ParseException {

    SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
    Date firstDate = sdf.parse("06/24/2017");
    Date secondDate = sdf.parse("06/30/2017");

    long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime());
    long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);

    assertEquals(diff, 6);
}

2.2. Использованиеjava.time - начиная с Java 8

Теперь вычисление разницы станет более интуитивным, если мы используемLocalDate, LocalDateTime для представления двух дат (со временем или без него) в сочетании сPeriod иDuration:.

РазницаLocalDate:

@Test
public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
    LocalDate now = LocalDate.now();
    LocalDate sixDaysBehind = now.minusDays(6);

    Period period = Period.between(now, sixDaysBehind);
    int diff = period.getDays();

    assertEquals(diff, 6);
}

СлучайLocalDateTime:

@Test
public void givenTwoDateTimesInJava8_whenDifferentiating_thenWeGetSix() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime sixMinutesBehind = now.minusMinutes(6);

    Duration duration = Duration.between(now, sixMinutesBehind);
    long diff = Math.abs(duration.toMinutes());

    assertEquals(diff, 6);
}

Here 'немного подробнее об этом API.

2.3. Использованиеjava.time.temporal.ChronoUnit для определения разницы в секундах

API времени в Java 8 представляет собой единицу даты и времени, например секунды или дни, используяTemporalUnit interface. Each unit provides an implementation for a method named between to calculate the amount of time between two temporal objects in terms of that specific unit.

Например, чтобы вычислить секунды между двумяLocalDateTimes:

@Test
public void givenTwoDateTimesInJava8_whenDifferentiatingInSeconds_thenWeGetTen() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime tenSecondsLater = now.plusSeconds(10);

    long diff = ChronoUnit.SECONDS.between(now, tenSecondsLater);

    assertEquals(diff, 10);
}

ChronoUnit предоставляет набор конкретных единиц времени, реализуя интерфейсTemporalUnit. It’s highly recommended to static import the ChronoUnit enum values to achieve more readability:

import static java.time.temporal.ChronoUnit.SECONDS;

// omitted
long diff = SECONDS.between(now, tenSecondsLater);

Кроме того, мы можем передать любые два совместимых временных объекта методуbetween , дажеZonedDateTime.

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

@Test
public void givenTwoZonedDateTimesInJava8_whenDifferentiating_thenWeGetSix() {
    LocalDateTime ldt = LocalDateTime.now();
    ZonedDateTime now = ldt.atZone(ZoneId.of("America/Montreal"));
    ZonedDateTime sixMinutesBehind = now
      .withZoneSameInstant(ZoneId.of("Asia/Singapore"))
      .minusMinutes(6);

    long diff = ChronoUnit.MINUTES.between(sixMinutesBehind, now);

    assertEquals(diff, 6);
}

2.4. Используяjava.time.temporal.Temporaluntil()

Любой объектTemporal, например LocalDate or ZonedDateTime, provides an until method to calculate the amount of time until another temporal in terms of the specified unit:

@Test
public void givenTwoDateTimesInJava8_whenDifferentiatingInSecondsUsingUntil_thenWeGetTen() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime tenSecondsLater = now.plusSeconds(10);

    long diff = now.until(tenSecondsLater, ChronoUnit.SECONDS);

    assertEquals(diff, 10);
}

Temporal#until иTemporalUnit#between  - это два разных API для одной и той же функциональности.

3. Внешние библиотеки

3.1. JodaTimeс

Мы также можем сделать относительно простую реализацию сJodaTime:


    joda-time
    joda-time
    2.9.9

Вы можете получить последнюю версиюJoda-time из Maven Central.

СлучайLocalDate:

@Test
public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() {
    LocalDate now = LocalDate.now();
    LocalDate sixDaysBehind = now.minusDays(6);

    Period period = new Period(now, sixDaysBehind);
    long diff = Math.abs(period.getDays());

    assertEquals(diff, 6);
}

Точно так же сLocalDateTime это:

@Test
public void givenTwoDateTimesInJodaTime_whenDifferentiating_thenWeGetSix() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime sixMinutesBehind = now.minusMinutes(6);

    Period period = new Period(now, sixMinutesBehind);
    long diff = Math.abs(period.getDays());
}

3.2. Date4Jс

Date4j также обеспечивает прямую и простую реализацию без примечания, что в этом случае нам нужно явно предоставитьTimeZone.

Начнем с зависимости Maven:


    com.darwinsys
    hirondelle-date4j
    1.5.1

Вот быстрый тест, работающий со стандартнымDateTime:

@Test
public void givenTwoDatesInDate4j_whenDifferentiating_thenWeGetSix() {
    DateTime now = DateTime.now(TimeZone.getDefault());
    DateTime sixDaysBehind = now.minusDays(6);

    long diff = Math.abs(now.numDaysFrom(sixDaysBehind));

    assertEquals(diff, 6);
}

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

В этом руководстве мы проиллюстрировали несколько способов вычисления разницы между датами (со временем и без него) как в простой Java, так и с использованием внешних библиотек.

Полный исходный код статьи доступенover on GitHub.