Разница между двумя датами в Java
1. обзор
В этом кратком обзоре мы рассмотрим несколько возможностей вычисления разницы между двумя датами на Java.
Дальнейшее чтение:
Дата приращения в Java
Обзор различных основных и сторонних методов для добавления дней к дате
Проверьте, является ли строка действительной датой в Java
Взгляните на разные способы проверить, является ли String действительной датой в Java
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.