Diferença entre duas datas em Java
1. Visão geral
Neste rápido artigo, exploraremos várias possibilidades de cálculo da diferença entre duas datas em Java.
Leitura adicional:
Data do incremento em Java
Uma visão geral de vários métodos principais e de terceiros para adicionar dias a uma data
Verifique se uma string é uma data válida em Java
Veja maneiras diferentes de verificar se uma String é uma data válida em Java
2. Java principal
2.1. Usandojava.util.Date para encontrar a diferença em dias
Vamos começar usando as principais APIs Java para fazer o cálculo e determinar o número de dias entre as duas datas:
@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. Usandojava.time - desde Java 8
Agora, calcular a diferença é mais intuitivo se usarmosLocalDate, LocalDateTime para representar as duas datas (com ou sem hora) em combinação comPeriodeDuration:
A diferença deLocalDate:
@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);
}
O casoLocalDateTime:
@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 é um pouco mais detalhado sobre esta API.
2.3. Usandojava.time.temporal.ChronoUnit para encontrar a diferença em segundos
A API de horário no Java 8 representa uma unidade de data e hora, por exemplo segundos ou dias, usandoTemporalUnit 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.
Por exemplo, para calcular os segundos entre doisLocalDateTimes:
@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 fornece um conjunto de unidades de tempo concretas implementando a interfaceTemporalUnit. 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);
Além disso, podemos passar quaisquer dois objetos temporais compatíveis para o métodobetween , até mesmo oZonedDateTime.
O que é ótimo sobreZonedDateTime é que o cálculo funcionará mesmo se eles estiverem configurados para fusos horários diferentes:
@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. Usandojava.time.temporal.Temporaluntil()
Qualquer objetoTemporal, por exemplo 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);
}
OsTemporal#untileTemporalUnit#between são duas APIs diferentes para a mesma funcionalidade.
3. Bibliotecas externas
3.1. JodaTime
Também podemos fazer uma implementação relativamente simples comJodaTime:
joda-time
joda-time
2.9.9
Você pode obter a versão mais recente deJoda-time no Maven Central.
LocalDate caso:
@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);
}
Da mesma forma, comLocalDateTime é:
@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 também fornece uma implementação direta e simples, sem a observação de que, neste caso, precisamos fornecer explicitamente umTimeZone.
Vamos começar com a dependência Maven:
com.darwinsys
hirondelle-date4j
1.5.1
Aqui está um teste rápido trabalhando com oDateTime padrão:
@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. Conclusão
Neste tutorial, ilustramos algumas maneiras de calcular a diferença entre datas (com e sem hora), tanto em Java simples quanto em bibliotecas externas.
O código-fonte completo do artigo está disponívelover on GitHub.