Estoy usando la java.util.Date
clase de Java en Scala y quiero comparar un Date
objeto y la hora actual. Sé que puedo calcular el delta usando getTime ():
(new java.util.Date()).getTime() - oldDate.getTime()
Sin embargo, esto solo me deja con una long
representación de milisegundos. ¿Hay alguna forma más simple y agradable de obtener un delta de tiempo?
Date
,Calendar
ySimpleDateFormat
”.java.time.Period
y / oDuration
. Ver la respuesta de Basil Bourque a continuación .Respuestas:
La
Date
API de JDK está horriblemente rota, lamentablemente. Recomiendo usar la biblioteca Joda Time .Joda Time tiene un concepto de intervalo de tiempo :
EDITAR: Por cierto, Joda tiene dos conceptos:
Interval
para representar un intervalo de tiempo entre dos instantes de tiempo (representa el tiempo entre las 8 a.m. y las 10 a.m.), yDuration
eso representa un período de tiempo sin los límites de tiempo reales (por ejemplo, ¡representa dos horas!)Si solo le interesan las comparaciones de tiempo, la mayoría de las
Date
implementaciones (incluida la JDK) implementa unaComparable
interfaz que le permite utilizar elComparable.compareTo()
fuente
Comparable.compareTo()
noComparable.compare()
.java.time
paquete en Java 8 está inspirado en Joda-Time, pero no es un reemplazo directo. Cada uno tiene sus ventajas y desventajas. Afortunadamente no tienes que elegir entre ellos. Use cada uno por sus puntos fuertes siempre que tenga cuidado con susimport
declaraciones. Consulte esta otra respuesta, por ejemplo, java.time.Dif simple (sin lib)
Y luego puedes llamar:
para obtener la diferencia de las 2 fechas en la unidad de minutos.
TimeUnit
es decirjava.util.concurrent.TimeUnit
, una enumeración estándar de Java que va de nanos a días.Dif. Legible por humanos (sin lib)
http://ideone.com/5dXeu6
La salida es algo así
Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
, con las unidades ordenadas.Solo tiene que convertir ese mapa en una cadena fácil de usar.
Advertencia
Los fragmentos de código anteriores calculan una diferencia simple entre 2 instantes. Puede causar problemas durante un cambio de horario de verano, como se explica en esta publicación . Esto significa que si calcula la diferencia entre fechas sin hora, es posible que le falte un día / hora.
En mi opinión, la diferencia de fechas es algo subjetiva, especialmente en días. Puedes:
cuente la cantidad de tiempo transcurrido de 24 h: día + 1 - día = 1 día = 24 h
cuente la cantidad de tiempo transcurrido, cuidando el horario de verano: día + 1 - día = 1 = 24h (pero usando el horario de medianoche y el horario de verano podría ser 0 día y 23h)
cuente el número de
day switches
, lo que significa día + 1 1pm - día 11am = 1 día, incluso si el tiempo transcurrido es solo 2h (o 1h si hay un horario de verano: p)Mi respuesta es válida si su definición de fecha difiere en los días que coinciden con el primer caso
Con JodaTime
Si está utilizando JodaTime, puede obtener la diferencia durante 2 instantes (Millones respaldados por ReadableInstant) con:
Pero también puede obtener la diferencia para las fechas / horas locales:
fuente
Tenga en cuenta que esto funciona con las fechas UTC, por lo que la diferencia puede ser un día libre si mira las fechas locales. Y lograr que funcione correctamente con las fechas locales requiere un enfoque completamente diferente debido al horario de verano.
fuente
(endDate.getTime() - startDate.getTime())
que se conviertan enint
lugar del resultado final, y obtiene un desbordamiento de enteros.Usando el marco java.time integrado en Java 8+:
Salida:
Para obtener más información, consulte el Tutorial de Oracle y el estándar ISO 8601 .
fuente
Period
lugar deDuration
para fechas.Necesita definir su problema más claramente. Usted podría simplemente tomar el número de milisegundos entre los dos
Date
objetos y se dividen por el número de milisegundos en 24 horas, por ejemplo, pero ...:Date
siempre está en UTCfuente
tl; dr
Convertir sus obsoletos
java.util.Date
objetos para su sustitución,java.time.Instant
. Luego calcule el tiempo transcurrido como aDuration
.Formato ISO 8601:
PnYnMnDTnHnMnS
El estándar sensible ISO 8601 define una representación textual concisa de un lapso de tiempo como un número de años, meses, días, horas, etc. El estándar llama a dicho lapso una duración . El formato es
PnYnMnDTnHnMnS
dondeP
significa "Período",T
separa la porción de fecha de la porción de tiempo, y en el medio hay números seguidos de una letra.Ejemplos:
P3Y6M4DT12H30M5S
tres años, seis meses, cuatro días, doce horas, treinta minutos y cinco segundos
PT4H30M
Cuatro horas y media
java.time
El marco java.time integrado en Java 8 y posterior suplanta a las viejas
java.util.Date
/java.util.Calendar
clases problemáticas . Las nuevas clases están inspiradas en el exitoso marco Joda-Time , pensado como su sucesor, similar en concepto pero rediseñado. Definido por JSR 310 . Ampliado por el proyecto ThreeTen-Extra . Ver el tutorial .Momento
La
Instant
clase representa un momento en la línea de tiempo en UTC con una resolución de nanosegundos (hasta nueve (9) dígitos de una fracción decimal).Lo mejor es evitar las clases heredadas como
Date
/Calendar
. Pero si debe interactuar con el código antiguo que aún no se ha actualizado a java.time , realice la conversión de un lado a otro. Llame a nuevos métodos de conversión agregados a las clases antiguas. Para pasar de unajava.util.Date
a unaInstant
, llameDate::toInstant
.Lapso de tiempo
Las clases java.time han dividido esta idea de representar un lapso de tiempo como varios años, meses, días, horas, minutos, segundos en dos mitades:
Period
por años, meses, díasDuration
por días, horas, minutos, segundosAquí hay un ejemplo.
Volcado a la consola.
Tanto
Period
yDuration
utilizar el ISO 8601 estándar para la generación de una representación de cadena de su valor.Java 9 agrega métodos para
Duration
obtener la parte de días, parte de horas, parte de minutos y parte de segundos.Puede obtener el número total de días u horas o minutos o segundos o milisegundos o nanosegundos en toda la Duración.
En Java 9, la
Duration
clase obtiene nuevos métodos para devolver las distintas partes de días, horas, minutos, segundos, milisegundos / nanosegundos. Llamar a losto…Part
métodos:toDaysPart()
,toHoursPart()
y así sucesivamente.ChronoUnit
Si solo le importa una mayor granularidad de tiempo más simple, como "número de días transcurridos", use la
ChronoUnit
enumeración.Otro ejemplo.
Sobre java.time
El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora como
java.util.Date
,Calendar
, ySimpleDateFormat
.El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a java.time.
Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .
¿Dónde obtener las clases java.time?
El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Usted puede encontrar algunas clases útiles aquí, como
Interval
,YearWeek
,YearQuarter
, y más .Joda-Time
ACTUALIZACIÓN: El proyecto Joda-Time ahora está en modo de mantenimiento , con el equipo que aconseja la migración a las clases java.time . Dejo esta sección intacta para la historia.
La biblioteca Joda-Time utiliza ISO 8601 para sus valores predeterminados. Su
Period
clase analiza y genera estas cadenas PnYnMnDTnHnMnS.Renders:
fuente
Period
,Duration
yChronoUnit
, tres clases cuya finalidad es determinar el delta entre los puntos de tiempo. Indique qué partes de mi "muro de texto" son irrelevantes. Y es incorrecto al decir que la Pregunta solicitó un "delta entre fechas": la Pregunta solicitó un delta entreDate
objetos, que son momentos de fecha y hora, no "fechas" a pesar del desafortunado nombre de esa clase.java.util.Date
a anInstant
(solo llame.toInstant
). Y agregué laMoment
sección para explicar. Usted mencionó un par deDate
objetos, pero en realidad la Pregunta usa solo unDate
objeto existente y luego captura el momento actual, así que hice lo mismo. ¡Gracias por la respuesta! Consejo: Renunciar al usoDate
: esas clases heredadas son realmente un desastre horrible.https://www.joda.org/joda-time/faq.html#datediff
fuente
Una alternativa un poco más simple:
En cuanto a "más agradable": bueno, ¿qué necesitas exactamente? El problema con la representación de las duraciones de tiempo como un número de horas y días, etc. es que puede conducir a imprecisiones y expectativas incorrectas debido a la complejidad de las fechas (por ejemplo, los días pueden tener 23 o 25 horas debido al horario de verano).
fuente
El uso del enfoque de milisegundos puede causar problemas en algunas configuraciones regionales.
Tomemos, por ejemplo, la diferencia entre las dos fechas 24/03/2007 y 25/03/2007 debería ser 1 día;
Sin embargo, con la ruta de milisegundos, ¡obtendrá 0 días si ejecuta esto en el Reino Unido!
La mejor manera de implementar esto es usar java.util.Calendar
fuente
Hay muchas maneras de encontrar la diferencia entre fechas y horas. Una de las formas más simples que conozco sería:
La declaración de impresión es solo un ejemplo: puede formatearla de la manera que desee.
fuente
Dado que todas las respuestas aquí son correctas, pero usan bibliotecas heredadas de Java o de terceros como joda o similar, simplemente dejaré caer otra forma usando nuevas clases java.time en Java 8 y posteriores. Vea el tutorial de Oracle .
Uso
LocalDate
yChronoUnit
:fuente
Restando las fechas en milisegundos obras (como se describe en otro post), pero usted tiene que utilizar HOUR_OF_DAY y no por hora cuando la limpieza de las partes de la hora de fechas:
fuente
Si no desea utilizar JodaTime o similar, la mejor solución es probablemente esta:
El número de ms por día no siempre es el mismo (debido al horario de verano y los segundos bisiestos), pero está muy cerca, y al menos las desviaciones debidas al horario de verano se cancelan durante períodos más largos. Por lo tanto, dividir y luego redondear dará un resultado correcto (al menos siempre que el calendario local utilizado no contenga saltos de tiempo extraños que no sean DST y segundos intercalares).
Tenga en cuenta que esto todavía asume eso
date1
ydate2
está configurado a la misma hora del día. Para diferentes momentos del día, primero debe definir qué significa "diferencia de fecha", como lo señaló Jon Skeet.fuente
date1.getTime()
contradate2.getTime()
. Por lo tanto, diferenciar 2016-03-03 a 2016-03-31 calculará 27 días, mientras que usted querría 28 días.Math.round()
, eso parece seguro en los calendarios del "mundo real". Perdón por el ruido.Eche un vistazo a Joda Time , que es una API de fecha / hora mejorada para Java y debería funcionar bien con Scala.
fuente
Permítanme mostrar la diferencia entre Joda Interval y Days:
fuente
Si necesita una cadena de retorno con formato como "2 días 03h 42m 07s", intente esto:
fuente
std
lo anterior no está definido.Nota: startDate y endDates son -> java.util.Date
y fecha de finalización
Similar a los días, también puede obtener horas, minutos y segundos.
fuente
Consulte el ejemplo aquí http://www.roseindia.net/java/beginners/DateDifferent.shtml Este ejemplo le brinda la diferencia en días, horas, minutos, segundos y milisegundos :).
fuente
Use la zona horaria GMT para obtener una instancia del Calendario, establezca la hora utilizando el método establecido de la clase Calendario. La zona horaria GMT tiene un desplazamiento de 0 (no realmente importante) y el indicador de horario de verano está establecido en falso.
fuente
java.util.Date
etc. El uso del truco para establecer la zona horaria en GMT hace que el código sea insensible a los efectos del horario de verano.El siguiente código puede darle el resultado deseado:
fuente
fuente
fuente
Date
, por lo que esta comparación es la mejor que se puede lograr dadas las circunstancias.Lo mejor que puedes hacer es
Ese número es el número de milisegundos en un día.
Una fecha-otra fecha te da la diferencia en milisegundos.
Recoge la respuesta en una variable doble .
fuente
Aquí hay una solución correcta de Java 7 en O (1) sin ninguna dependencia.
fuente
Esa es probablemente la forma más sencilla de hacerlo, tal vez porque he estado codificando en Java (con sus bibliotecas de fecha y hora ciertamente torpes) durante un tiempo, ¡pero ese código me parece "simple y agradable"!
¿Está satisfecho con el resultado que se devuelve en milisegundos, o es parte de su pregunta que preferiría que se devuelva en algún formato alternativo?
fuente
No utiliza la API estándar, no. Puedes rodar el tuyo haciendo algo como esto:
O puedes usar Joda :
fuente
Solo para responder la pregunta inicial:
Ponga el siguiente código en una función como Long getAge () {}
Lo más importante aquí es trabajar con números largos al multiplicar y dividir. Y, por supuesto, el desplazamiento que aplica Java en su cálculo de fechas.
:)
fuente
Como la pregunta está etiquetada con Scala,
fuente
Después de leer todas las otras respuestas, para mantener el tipo de fecha de Java 7 pero ser más preciso / estándar con el enfoque de Java 8 diff,
fuente
prueba esto:
Puede editar la cadena en el parámetro parse ().
fuente