Tengo un malentendido al administrar las fechas en Java cuando quiero calcular el lapso en número de días entre dos fechas.
Digamos que tenemos dos fechas diferentes:
Caso 1: tengo este fragmento de código usando Fechas:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date dt1 = format.parse("1986-01-24"); Date dt2 = format.parse("2017-04-20"); int intSpanInDays= (int) ((dt2.getTime() - dt1.getTime()) / (1000 * 60 * 60 * 24)); System.out.println("Days between: " + intSpanInDays);Salida 1:
Days between: 11408 Caso 2: Fragmento de código usando Calendario:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); GregorianCalendar cal1 = new GregorianCalendar(); cal1.setTime(format.parse("1986-01-24")); cal1.set(Calendar.HOUR, 0); cal1.set(Calendar.MINUTE, 0); cal1.set(Calendar.SECOND, 0); GregorianCalendar cal2 = new GregorianCalendar(); cal2.setTime(format.parse("2017-04-20")); cal2.set(Calendar.HOUR, 0); cal2.set(Calendar.MINUTE, 0); cal2.set(Calendar.SECOND, 0); long spanInMillis = cal2.getTimeInMillis() - cal1.getTimeInMillis(); GregorianCalendar cal3 = new GregorianCalendar(); cal3.setTimeInMillis(spanInMillis); long millisInADay = 1000 * 60 * 60 * 24; System.out.println("Days between: " + (cal3.getTimeInMillis() / millisInADay));Salida 2:
Days between: 11408Caso 3: Ejemplo utilizando una hoja de cálculo en Excel:
Cuando uso MS Excel para obtener este lapso simplemente introduciendo las fechas dadas y simplemente restando, el resultado es este:
PREGUNTA
¿Por qué falta un día el código de cálculo de fecha de Java? ¿Qué falta o está mal en cualquiera de los casos 1 y 2 que no coincide con el resultado en el caso 3?
La hoja de cálculo tiene en cuenta el horario de verano y sus cálculos se truncan ingenuamente, y dado que hay un día más de 23 horas en el intervalo que los días de 25 horas, el resto de 23 horas se trunca, lo que arroja un resultado de un día menos de La respuesta correcta.
JDK 8 simplifica en gran medida estos cálculos con su nueva API de fecha y hora. Lo mismo se puede hacer con precisión y simplemente usando el siguiente código:
LocalDate date1 = LocalDate.of(1986, 01, 24); LocalDate date2 = LocalDate.of(2017, 04, 20); System.out.println(date1.until(date2, ChronoUnit.DAYS));Esto se ocupa automáticamente de todos los cambios de horario de verano, años bisiestos, etc., que en su mayoría se pasan por alto al intentar hacer los cálculos manualmente.