Diferença entre duas datas em Java

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

Read more

Verifique se uma string é uma data válida em Java

Veja maneiras diferentes de verificar se uma String é uma data válida em Java

Read more

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.