online milisegundos long from currenttimemillis convertir convert java scala date long-integer gregorian-calendar

milisegundos - java timestamp to date



¿Qué sucedió entre el 28 de marzo y el 29 de marzo de 1976 con el java.util.GregorianCalendar? (3)

Tratando de usar el calendario de Gregorian, me quedé atascado en una singularidad al calcular el número de días desde una fecha en particular. En el intérprete de scala, ingresé

scala>import java.util.GregorianCalendar scala>import java.util.Calendar scala>val dateToday = new GregorianCalendar(2012,Calendar.MAY,22).getTimeInMillis() dateToday: Long = 1337637600000 scala>val days1 = (dateToday - (new GregorianCalendar(1976,Calendar.MARCH,28).getTimeInMillis())) / (1000*3600*24) days1: Long = 13203 scala>val days2 = (dateToday - (new GregorianCalendar(1976,Calendar.MARCH,29).getTimeInMillis())) / (1000*3600*24) days2: Long = 13203

No sé si el hecho de que 1976 sea un año bisiesto es importante, pero los días 1 y 2 deberían haberse separado por 1. Este es el único momento en la historia desde 1970 en que ocurre esta singularidad.

Queriendo saber qué está pasando, calculo la diferencia entre las dos fechas mencionadas anteriormente, ¡y me da exactamente 23 horas de diferencia! ¿Qué pasó en esa fecha? Wikipedia aparentemente no dice nada al respecto.

Y aún más importante, ¿cómo calcular el número real de días desde una fecha en particular?


El problema

Los días de ahorro de luz diurna solo duran 23 horas.

Y de acuerdo con this 28 de marzo de 1976, fue un día de ahorro de energía en al menos París. La hora entre la 1 am y las 2 am en ese día simplemente no existía.

Aunque debe ser un problema de configuración regional, ya que en mi computadora lo hago bien:

scala> val days1 = (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 28).getTimeInMillis())) / (1000 * 3600 * 24) days1: Long = 13203 scala> val days2 = (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 29).getTimeInMillis())) / (1000 * 3600 * 24) days2: Long = 13202

No estoy en París ni en ningún otro lugar que haya cambiado de horario ese día; La hora cambió el 25 de abril de 1976 donde estoy. Entonces obtengo el comportamiento de "día omitido" en esa fecha:

scala> val days3 = (dateToday - (new GregorianCalendar(1976, Calendar.APRIL, 25).getTimeInMillis())) / (1000 * 3600 * 24) days3: Long = 13175 scala> val days4 = (dateToday - (new GregorianCalendar(1976, Calendar.APRIL, 26).getTimeInMillis())) / (1000 * 3600 * 24) days4: Long = 13175

Erwin señala en los comentarios que la razón probable por la que usted solo nota la diferencia de fecha incorrecta aquí es que todos los demás días de ahorro de luz natural se compensan con los días de 25 horas que también ocurren en esos años, cuando se corrige el día de ahorro de energía.

La solución

Utilice una mejor biblioteca para el procesamiento de la fecha. La biblioteca de joda-time hace correctamente (además de ser un mejor marco de fecha / hora en general):

import org.joda.time.Days import org.joda.time.DateTimeConstants import org.joda.time.DateMidnight val d1 = new DateMidnight(1976, DateTimeConstants.APRIL, 25) val d2 = new DateMidnight(1976, DateTimeConstants.APRIL, 26) val x = Days.daysBetween(d1, d2).getDays() println(x) // 1


Si la opción de una división flotante no está disponible, la mejor respuesta que se me ocurre es agregar una hora (1000 * 3600) al calcular una diferencia entre dos días:

scala> (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 28).getTimeInMillis()) + 1000*3600) / (1000 * 3600 * 24) days1: Long = 13204 scala> (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 29).getTimeInMillis()) + 1000*3600) / (1000 * 3600 * 24) days1: Long = 13203

Debería funcionar para todas las fechas, ya que ya no sufres más horas de salto.


dhg señaló lo que pienso: este día es un día de "horario de verano". Como este día solo dura 23 horas, la división euclidiana por día equivale a 0.

De hecho, el uso de objetos GregorianCalendar solo usa una fecha como milisegundos, por lo que dividir por un día como un número entero solo trunca un resultado.

En lugar de una división euclidiana (entero), intente hacer una división flotante, luego redondee el resultado.