Calcola i giorni tra due date in Java 8


251

So che ci sono molte domande su SO su come ottenere, ma voglio ed esempio usare la nuova API Java 8 Date. Conosco anche la libreria JodaTime, ma voglio un modo di lavorare senza librerie esterne.

La funzione deve lamentarsi di queste restrizioni:

  1. Prevenire gli errori dalla data di salvataggio
  2. Gli input sono due oggetti Date (senza ora, so localdatetime, ma devo fare con le istanze date)

2
Qualcosa del genere per esempio ?
MadProgrammer,

@MadProgrammer Non proprio - La durata non è la soluzione migliore per farlo ...
assylias

@assylias Beh, è ​​meglio di quello che aveva l'OP
MadProgrammer,

@assylias Allora cos'è?
MadProgrammer,

16
@MadProgrammer DAYS.between(localDate1, localDate2).
Assylias,

Risposte:


435

Se si desidera giorni di calendario logici , utilizzare il DAYS.between()metodo da java.time.temporal.ChronoUnit:

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

Se vuoi letteralmente 24 ore al giorno , (una durata ), puoi invece usare la 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

Per ulteriori informazioni, consultare questo documento .


15
Ciò genera un'eccezione, poiché il metodo Duration.b Between richiede oggetti temporali in grado di supportare l'unità SECONDS . Invece, prova Duration.between(today.atTime(0, 0), yesterday.atTime(0, 0)).toDays().
VGR,

5
Invece di today.atTime(0, 0)te puoi fare today.atStartOfDay().
Eee,

5
@REACHUS Forse -1 è stato un po 'duro perché il codice che proponi funziona, ma Durata ha lo scopo di misurare "quantità di tempo basate sul tempo". Esiste un modo integrato per misurare un numero di giorni che non richiede la conversione da data a data / ora.
Assylias,

La risposta migliore per LocalDate è la risposta di @Sunil B di seguito:ChronoUnit.DAYS.between(firstDate, secondDate)
Lappro,

@Lappro perché è meglio? Utilizza lo stesso metodo della mia risposta
syntagma,

130

Sulla base dei commenti di VGR ecco cosa puoi usare:

ChronoUnit.DAYS.between(firstDate, secondDate)

38

Puoi usare 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
Il gotcha che ho appena incontrato con la prima versione di untilè che restituisce un oggetto Period . Ciò restituirà un numero di anni / mesi / giorni tra le due date, non il numero effettivo di giorni. E getDays () nel Periodo restituisce solo la parte dei giorni (non tenendo conto del numero di anni o mesi), anziché del numero totale di giorni. La seconda versione funziona esattamente come desiderato per ottenere un numero di giorni tra due date.
M. Justin,

C'è un'alternativa completa per questo per questo? Poiché ha bisogno di Android SDk 26 e versioni successive
ralphgabb

12

Puoi usare DAYS.betweendajava.time.temporal.ChronoUnit

per esempio

import java.time.temporal.ChronoUnit;

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

10

Se startDate e endDate sono istanza di java.util.Date

Possiamo usare il metodo Between () dall'enum di ChronoUnit :

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

ChronoUnit.DAYS conta i giorni completati 24 ore .

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

Usa i GIORNI in enum java.time.temporal.ChronoUnit . Di seguito è riportato il codice di esempio:

Output: * Numero di giorni tra la data di inizio: 01-03-2015 e la data di fine: 03-03-2016 è ==> 368. ** Numero di giorni tra la data di inizio: 03-03-2016 e data di fine: 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

Tutti dicono di usare ChronoUnit.DAYS.b Between ma che si limita a delegare a un altro metodo che potresti chiamare tu stesso. Quindi potresti anche farlo firstDate.until(secondDate, ChronoUnit.DAYS).

I documenti per entrambi in realtà menzionano entrambi gli approcci e dicono di usare quello che è più leggibile.


FWIW ... Non sono sicuro del perché entrambi esistano. Ci sono volte in cui una è più leggibile e altre in un'altra? Quando perché?
nafg

5

Ecco qui:

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

Ottieni il numero di giorni prima di Natale dal giorno corrente, prova questo

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

3

Se l'obiettivo è solo quello di ottenere la differenza in pochi giorni e poiché le risposte sopra menzionate menzionano i metodi delegati, vorrei sottolineare che una volta può anche semplicemente usare:

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

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

1
In autunno nella trappola usare 'Period.b Between (date1, date2) .getDays ()' senza rendersi conto che perdi i mesi e gli anni della differenza.
MrSmith42,

2

ottenere giorni tra due date la data è l'istanza di java.util.Date

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

1

So che questa domanda è per Java 8, ma con Java 9 potresti usare:

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

0

Usa la classe o il metodo più adatto alle tue esigenze:

  • la classe di durata ,
  • Classe del periodo ,
  • o il metodo ChronoUnit.between .

Una durata misura un periodo di tempo utilizzando valori basati sul tempo (secondi, nanosecondi).

Un periodo utilizza valori basati sulla data (anni, mesi, giorni).

Il metodo ChronoUnit.between è utile quando si desidera misurare un intervallo di tempo in un'unica unità di tempo, ad esempio giorni o secondi.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.