Calcular dias entre duas datas no Java 8


250

Eu sei que há muitas perguntas sobre SO sobre como obter, mas eu quero e exemplo usando a nova API do Java 8 Date. Eu também conheço a biblioteca JodaTime, mas quero uma maneira de trabalhar sem bibliotecas externas.

A função precisa reclamar com estas restrições:

  1. Evitar erros a partir da data de economia
  2. Entrada são dois objetos de Data (sem hora, eu sei localdatetime, mas preciso fazer com instâncias de data)

2
Algo assim por exemplo ?
— MadProgrammer

@MadProgrammer Não é verdade - Duração não é o mais adequado para fazer isso ...
— assylias

@assylias Bem, é melhor do que o que o OP teve
— MadProgrammer

@assylias Então, o que é?
— MadProgrammer

16
@MadProgrammer DAYS.between(localDate1, localDate2).
— Assilias

Respostas:


434

Se você deseja dias lógicos de calendário , use o DAYS.between()método de java.time.temporal.ChronoUnit:

LocalDate dateBefore;
LocalDate dateAfter;
long daysBetween = DAYS.between(dateBefore, dateAfter);

Se você quiser dias literais de 24 horas (uma duração ), poderá usar a Durationclasse:

LocalDate today = LocalDate.now()
LocalDate yesterday = today.minusDays(1);
// Duration oneDay = Duration.between(today, yesterday); // throws an exception
Duration.between(today.atStartOfDay(), yesterday.atStartOfDay()).toDays() // another option

Para mais informações, consulte este documento .


15
Isso gera uma exceção, porque o método Duration.between requer objetos temporais capazes de suportar a unidade SECONDS . Em vez disso, tente Duration.between(today.atTime(0, 0), yesterday.atTime(0, 0)).toDays().
— VGR

5
Em vez de today.atTime(0, 0)você pode fazer today.atStartOfDay().
— eee

5
@REACHUS Talvez o -1 tenha sido um pouco duro porque o código que você propõe funciona, mas o Duration deve medir "quantidades de tempo baseadas no tempo". Existe uma maneira integrada de medir um número de dias que não requer conversão de data para data e hora.
— Assilias

A melhor resposta para o LocalDate é a resposta de @Sunil B abaixo:ChronoUnit.DAYS.between(firstDate, secondDate)
— Lappro

@ Lappro por que é melhor? Ele usa o mesmo método da minha resposta
— syntagma

130

Com base nos comentários do VGR, aqui está o que você pode usar:

ChronoUnit.DAYS.between(firstDate, secondDate)

38

Você pode usar until():

LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4);
LocalDate christmas = LocalDate.of(2014, Month.DECEMBER, 25);

System.out.println("Until christmas: " + independenceDay.until(christmas));
System.out.println("Until christmas (with crono): " + independenceDay.until(christmas, ChronoUnit.DAYS));

4
O problema que acabei de encontrar com a primeira versão untilé que ele retorna um objeto Period . Isso retornará vários anos / meses / dias entre as duas datas, não o número real de dias. E getDays () no Período retorna apenas a parte dos dias (sem levar em consideração o número de anos ou meses), em vez do número total de dias. A segunda versão funciona exatamente como desejado para obter um número de dias entre duas datas.
— 28718 Justin M.

Existe uma alternativa completa para isso? Desde que precisa SDK para Android 26 e acima
— ralphgabb

12

Você pode usar DAYS.betweendejava.time.temporal.ChronoUnit

por exemplo

import java.time.temporal.ChronoUnit;

public long getDaysCountBetweenDates(LocalDate dateBefore, LocalDate dateAfter) {
    return DAYS.between(dateBefore, dateAfter);
}

10

Se startDate e endDate forem instância de java.util.Date

Podemos usar o método between () do ChronoUnit enum:

public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
    //..
}

ChronoUnit.DAYS contam dias que completaram 24 horas .

import java.time.temporal.ChronoUnit;

ChronoUnit.DAYS.between(startDate.toInstant(), endDate.toInstant());

//OR 

ChronoUnit.DAYS.between(Instant.ofEpochMilli(startDate.getTime()), Instant.ofEpochMilli(endDate.getTime()));

8

Use os DAYS no enum java.time.temporal.ChronoUnit . Abaixo está o código de exemplo:

Saída: * Número de dias entre a data de início: 01/03/2015 e a data de término: 03-03-2016 é ==> 368. ** Número de dias entre a data de início: 03-03-2016 e a data de término: 01/03/2015 é ==> -368 *

package com.bitiknow.date;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

/**
 * 
 * @author pradeep
 *
 */
public class LocalDateTimeTry {
    public static void main(String[] args) {

        // Date in String format.
        String dateString = "2015-03-01";

        // Converting date to Java8 Local date
        LocalDate startDate = LocalDate.parse(dateString);
        LocalDate endtDate = LocalDate.now();
        // Range = End date - Start date
        Long range = ChronoUnit.DAYS.between(startDate, endtDate);
        System.out.println("Number of days between the start date : " + dateString + " and end date : " + endtDate
                + " is  ==> " + range);

        range = ChronoUnit.DAYS.between(endtDate, startDate);
        System.out.println("Number of days between the start date : " + endtDate + " and end date : " + dateString
                + " is  ==> " + range);

    }

}

8

Todo mundo está dizendo para usar o ChronoUnit.DAYS.between, mas isso apenas delega para outro método que você poderia chamar. Então você também pode fazer firstDate.until(secondDate, ChronoUnit.DAYS).

Os documentos de ambos mencionam as duas abordagens e dizem para usar a que for mais legível.


FWIW ... Não sei por que os dois existem. Há momentos em que um é mais legível e momentos em que o outro é? Quando por que?
— Nafg

5

Aqui está:

public class DemoDate {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        System.out.println("Current date: " + today);

        //add 1 month to the current date
        LocalDate date2 = today.plus(1, ChronoUnit.MONTHS);
        System.out.println("Next month: " + date2);

        // Put latest date 1st and old date 2nd in 'between' method to get -ve date difference
        long daysNegative = ChronoUnit.DAYS.between(date2, today);
        System.out.println("Days : "+daysNegative);

        // Put old date 1st and new date 2nd in 'between' method to get +ve date difference
        long datePositive = ChronoUnit.DAYS.between(today, date2);
        System.out.println("Days : "+datePositive);
    }
}

5

Obtenha o número de dias antes do Natal do dia atual, tente isso

System.out.println(ChronoUnit.DAYS.between(LocalDate.now(),LocalDate.of(Year.now().getValue(), Month.DECEMBER, 25)));

3

Se o objetivo é apenas obter a diferença em dias e, como as respostas acima mencionam os métodos delegados, gostaria de salientar que uma vez também pode simplesmente usar:

public long daysInBetween(java.time.LocalDate startDate, java.time.LocalDate endDate) {
  // Check for null values here

  return endDate.toEpochDay() - startDate.toEpochDay();
}

1
Ao cair na armadilha, use 'Period.between (date1, date2) .getDays ()' sem perceber que você perde os meses e anos da diferença.
— MrSmith42

2

obter dias entre duas datas é uma instância de java.util.Date

public static long daysBetweenTwoDates(Date dateFrom, Date dateTo) {
            return DAYS.between(Instant.ofEpochMilli(dateFrom.getTime()), Instant.ofEpochMilli(dateTo.getTime()));
        }

1

Eu sei que esta pergunta é para Java 8, mas com o Java 9 você pode usar:

public static List<LocalDate> getDatesBetween(LocalDate startDate, LocalDate endDate) {
    return startDate.datesUntil(endDate)
      .collect(Collectors.toList());
}

0

Use a classe ou o método que melhor atenda às suas necessidades:

  • a classe Duration ,
  • Classe período
  • ou o método ChronoUnit.between .

A Duration mede uma quantidade de tempo usando valores baseados em tempo (segundos, nanossegundos).

Um Período usa valores baseados em data (anos, meses, dias).

O método ChronoUnit.between é útil quando você deseja medir uma quantidade de tempo em uma única unidade de tempo, como dias ou segundos.

https://docs.oracle.com/javase/tutorial/datetime/iso/period.html

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.