Calcular días entre dos fechas en Java 8

251

Sé que hay muchas preguntas sobre SO sobre cómo llegar, pero quiero y, por ejemplo, usar la nueva API Java 8 Date. También conozco la biblioteca JodaTime, pero quiero una forma de trabajo sin bibliotecas externas.

La función necesita quejarse con estas restricciones:

  1. Prevenir errores a partir de la hora de guardar la fecha
  2. Los datos de entrada son dos objetos de fecha (sin hora, sé hora local de fecha, pero tengo que ver con instancias de fecha)
Marcos
fuente
2
Algo como esto por ejemplo ?
MadProgrammer
En realidad, no @MadProgrammer - Duración no es la mejor forma de hacer eso ...
assylias
@assylias Bueno, es mejor de lo que tenía el OP
MadProgrammer
@assylias Entonces, ¿qué es?
MadProgrammer
16
@MadProgrammer DAYS.between(localDate1, localDate2).
Assylias

Respuestas:

435

Si desea días calendario lógicos , use el DAYS.between()método de java.time.temporal.ChronoUnit:

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

Si desea días de 24 horas literales (una duración ), puede usar la Durationclase en su lugar:

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 obtener más información, consulte este documento .

sintagma
fuente
15
Eso arroja una excepción, porque el método Duration.between requiere objetos temporales capaces de soportar la unidad SECONDS . En cambio, inténtalo Duration.between(today.atTime(0, 0), yesterday.atTime(0, 0)).toDays().
VGR
55
En lugar de today.atTime(0, 0)que puedas hacer today.atStartOfDay().
eee
55
@REACHUS Quizás el -1 fue un poco duro porque el código que propone funciona, pero la duración está destinada a medir "cantidades de tiempo basadas en el tiempo". Hay una forma integrada de medir una cantidad de días que no requiere la conversión de fecha a fecha y hora.
Assylias
La mejor respuesta para LocalDate es la respuesta de @Sunil B a continuación:ChronoUnit.DAYS.between(firstDate, secondDate)
Lappro
@Lappro ¿por qué es mejor? Utiliza el mismo método que mi respuesta
sintagma
130

Según los comentarios de VGR, esto es lo que puede usar:

ChronoUnit.DAYS.between(firstDate, secondDate)
Sunil B
fuente
38

Puedes 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));
nazar_art
fuente
44
El problema que acabo de encontrar con la primera versión untiles que devuelve un objeto Period . Eso devolverá una cantidad de años / meses / días entre las dos fechas, no la cantidad real de días. Y getDays () en el Período solo devuelve la parte de días (sin tener en cuenta la cantidad de años o meses), en lugar de la cantidad total de días. La segunda versión funciona exactamente como se desea para obtener una cantidad de días entre dos fechas.
M. Justin
¿Hay una alternativa completa para esto para esto? Como necesita Android SDk 26 y superior
ralphgabb
12

Puedes usar DAYS.betweendesdejava.time.temporal.ChronoUnit

p.ej

import java.time.temporal.ChronoUnit;

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

Si startDate y endDate son instancias de java.util.Date

Podemos usar el método between () de ChronoUnit enum:

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

ChronoUnit.DAYS cuenta días que completaron 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()));
Pawan
fuente
8

Use los DÍAS en enum java.time.temporal.ChronoUnit . A continuación se muestra el código de muestra:

Salida: * Número de días entre la fecha de inicio: 2015-03-01 y la fecha de finalización: 2016-03-03 es ==> 368. ** Número de días entre la fecha de inicio: 2016-03-03 y la fecha de finalización: 2015-03-01 es ==> -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);

    }

}
Pradeep Padmarajaiah
fuente
8

Todo el mundo dice que use ChronoUnit.DAYS.entre pero eso solo delega a otro método que podría llamarse usted mismo. Entonces también podrías hacerlo firstDate.until(secondDate, ChronoUnit.DAYS).

Los documentos para ambos en realidad mencionan ambos enfoques y dicen usar el que sea más legible.

nafg
fuente
FWIW ... No estoy seguro de por qué ambos existen. ¿Hay momentos en que uno es más legible y otros más? ¿Cuando por qué?
nafg
5

Aqui tienes:

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);
    }
}
Pra_A
fuente
5

Obtenga el número de días antes de Navidad del día actual, intente esto

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

Si el objetivo es solo obtener la diferencia en días y dado que las respuestas anteriores mencionan acerca de los métodos de delegado, me gustaría señalar que una vez también puede simplemente usar:

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

  return endDate.toEpochDay() - startDate.toEpochDay();
}
levenshtein
fuente
1
En otoño, en la trampa, use 'Period.between (date1, date2) .getDays ()' sin darse cuenta de que pierde los meses y años de la diferencia.
MrSmith42
2

obtener días entre dos fechas fecha es instancia de java.util.Date

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

Sé que esta pregunta es para Java 8, pero con Java 9 podría usar:

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

Use la clase o método que mejor satisfaga sus necesidades:

  • la clase de duración ,
  • Clase de período ,
  • o el método ChronoUnit.between .

Una duración mide una cantidad de tiempo utilizando valores basados ​​en el tiempo (segundos, nanosegundos).

Un período utiliza valores basados ​​en fechas (años, meses, días).

El método ChronoUnit.between es útil cuando desea medir una cantidad de tiempo en una sola unidad de tiempo, como días o segundos.

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

Samuel
fuente