Me gustaría tener un método compareTo que ignore la porción de tiempo de un java.util.Date. Supongo que hay varias formas de resolver esto. ¿Cuál es la forma más simple?
Actualización: aunque Joda Time era una buena recomendación en ese momento, use la java.time
biblioteca de Java 8+ en su lugar siempre que sea posible.
Mi preferencia es usar Joda Time, lo que hace que esto sea increíblemente fácil:
DateTime first = ...;
DateTime second = ...;
LocalDate firstDate = first.toLocalDate();
LocalDate secondDate = second.toLocalDate();
return firstDate.compareTo(secondDate);
EDITAR: Como se señaló en los comentarios, si lo usa DateTimeComparator.getDateOnlyInstance()
es aún más simple :)
// TODO: consider extracting the comparator to a field.
return DateTimeComparator.getDateOnlyInstance().compare(first, second);
("Use Joda Time" es la base de casi todas las preguntas SO sobre las que se pregunta java.util.Date
o java.util.Calendar
. Es una API completamente superior. Si está haciendo algo significativo con las fechas / horas, realmente debería usarlo si es posible).
Si se ve obligado a usar la API integrada, debe crear una instancia Calendar
con la fecha adecuada y con la zona horaria adecuada. Luego, puede establecer cada campo en cada calendario fuera de la hora, minuto, segundo y milisegundo a 0, y comparar los tiempos resultantes. Definitivamente asqueroso en comparación con la solución de Joda :)
La zona horaria parte es importante: java.util.Date
es siempre basada en UTC. En la mayoría de los casos en los que he estado interesado en una fecha, esa ha sido una fecha en una zona horaria específica . Eso por sí solo te obligará a usarCalendar
o Joda Time (a menos que desee contabilizar la zona horaria usted mismo, lo que no recomiendo).
Referencia rápida para desarrolladores de Android
//Add joda library dependency to your build.gradle file
dependencies {
...
implementation 'joda-time:joda-time:2.9.9'
}
Código de muestra (ejemplo)
DateTimeComparator dateTimeComparator = DateTimeComparator.getDateOnlyInstance();
Date myDateOne = ...;
Date myDateTwo = ...;
int retVal = dateTimeComparator.compare(myDateOne, myDateTwo);
if(retVal == 0)
//both dates are equal
else if(retVal < 0)
//myDateOne is before myDateTwo
else if(retVal > 0)
//myDateOne is after myDateTwo
Apache commons-lang es casi omnipresente. ¿Y qué hay de esto?
fuente
Si realmente quieres usar java.util.Date, harías algo como esto:
o, usando un calendario en su lugar (preferido, ya que getYear () y tales están en desuso)
fuente
Preferiría usar la biblioteca Joda insetad de
java.util.Date
directamente, ya que Joda hace una distinción entre fecha y hora (vea las clases YearMonthDay y DateTime ).Sin embargo, si desea utilizarlo
java.util.Date
, le sugiero que escriba un método de utilidad; p.ejfuente
¿Alguna opinión sobre esta alternativa?
fuente
==
operador no necesariamente devuelvetrue
cadenas equivalentes (usoequals()
). Ciertamente, tampoco puede usar los otros operadores de comparación que mencionó.sdf.format(date1).compareTo(sdf.format(date2));
.Si desea comparar solo el mes, día y año de dos fechas, el siguiente código funciona para mí:
Gracias Rob
fuente
Yo también prefiero Joda Time , pero aquí hay una alternativa:
EDITAR
Puse la cosa UTC a continuación en caso de que necesite comparar fechas para una zona horaria específica que no sea UTC. Sin embargo, si tienes esa necesidad, te aconsejo que vayas por Joda.
fuente
Math.abs(second.getTime() - first.getTime()) < 1000L*60*60*24
< oneDay
.tl; dr
Evite las clases de fecha y hora heredadas
Evite las viejas clases problemáticas de fecha y hora heredadas como
Date
&Calendar
, ahora suplantadas por las clases java.time.Usando java.time
A
java.util.Date
representa un momento en la línea de tiempo en UTC. El equivalente en java.time esInstant
. Puede convertir utilizando nuevos métodos agregados a la clase heredada.Quieres comparar por fecha. Una zona horaria es crucial para determinar una fecha. Para cualquier momento dado, la fecha varía en todo el mundo por zona. Por ejemplo, unos minutos después de la medianoche en París, Francia es un nuevo día mientras todavía "ayer" en Montreal Québec .
Especificar un nombre de zona horaria correcta en el formato de
continent/region
, por ejemploAmerica/Montreal
,Africa/Casablanca
oPacific/Auckland
. Nunca use el 3-4 abreviatura de letras tales comoEST
oIST
, ya que son no verdaderas zonas de tiempo, no estandarizados, y ni siquiera único (!).Aplica el
ZoneId
paraInstant
obtener unZonedDateTime
.La
LocalDate
clase representa un valor de solo fecha sin hora del día y sin zona horaria. Podemos extraer aLocalDate
de aZonedDateTime
, eliminando efectivamente la parte de la hora del día.Ahora comparar, utilizando métodos tales como
isEqual
,isBefore
, yisAfter
.Vea este código en vivo en IdeOne.com .
Sobre java.time
El marco java.time está integrado en Java 8 y posterior. 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 las clases 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 .fuente
Ya mencioné apache commons-utils :
le da un objeto Fecha que contiene solo fecha, sin hora, y puede compararlo con
Date.compareTo
fuente
Me temo que no hay un método para comparar dos fechas que podrían llamarse "fácil" o "simple".
Al comparar dos instancias de tiempo con cualquier tipo de precisión reducida (por ejemplo, solo comparar fechas), siempre debe tener en cuenta cómo la zona horaria afecta la comparación.
Si
date1
está especificando un evento que ocurrió en la zona horaria +2 ydate2
está especificando un evento que ocurrió en EST, por ejemplo, debe tener cuidado para comprender adecuadamente las implicaciones de la comparación.¿Su propósito es determinar si los dos eventos ocurrieron en la misma fecha del calendario en sus propias zonas horarias respectivas? ¿O necesita saber si las dos fechas caen en la misma fecha del calendario en una zona horaria específica (UTC o su TZ local, por ejemplo).
Una vez que descubres qué es lo que realmente estás tratando de comparar, solo es cuestión de obtener el triple de la fecha año-mes en una zona horaria apropiada y hacer la comparación.
El tiempo de Joda puede hacer que la operación de comparación real parezca mucho más limpia, pero la semántica de la comparación sigue siendo algo que debe descubrir usted mismo.
fuente
Si está utilizando Java 8, debe usar las
java.time.*
clases para comparar fechas; es preferible a las distintasjava.util.*
clasesp.ej; https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html
fuente
Si solo desea comparar dos fechas sin tiempo, el siguiente código podría ayudarlo:
fuente
Aquí hay una solución de este blog: http://brigitzblog.blogspot.com/2011/10/java-compare-dates.html
es decir, puede ver si la diferencia horaria en milisegundos es menor que la duración de un día.
fuente
``
``
fuente
No sé si es nuevo pensar o de lo contrario, pero te muestro como lo hice
fuente
Simplemente marque DAY_OF_YEAR en combinación con la propiedad YEAR
EDITAR:
Ahora podemos usar el poder de las funciones de extensión de Kotlin
fuente
En Java 8 puede usar LocalDate, que es muy similar al de Joda Time.
fuente
Esto lo ayudará a comparar fechas sin tener en cuenta la hora.
fuente
Usando getDateInstance de SimpleDateFormat, podemos comparar solo dos objetos de fecha sin tiempo. Ejecute el siguiente código.
fuente
Usando http://mvnrepository.com/artifact/commons-lang/commons-lang
fuente
DateUtils.isSameDay(date1, date2)
.Otro método simple de comparación basado en las respuestas aquí y mi guía de mentor
EDITAR : Según @Jonathan Drapeau, el código anterior falla algunos casos (me gustaría ver esos casos, por favor) y sugirió lo siguiente, según entiendo:
Tenga en cuenta que la clase Date está en desuso porque no era susceptible de internacionalización. ¡La clase Calendario se usa en su lugar!
fuente
getXxx
métodos obsoletos deDate
.Primero, tenga en cuenta que esta operación depende de la zona horaria. Por lo tanto, elija si desea hacerlo en UTC, en la zona horaria de la computadora, en su propia zona horaria favorita o dónde. Si aún no está convencido de que es importante, vea mi ejemplo al final de esta respuesta.
Como su pregunta no es muy clara sobre esto, supongo que tiene una clase con un campo de instancia que representa un punto en el tiempo y la implementación
Comparable
, y desea que el orden natural de sus objetos sea por fecha, pero no por hora , de ese campo. Por ejemplo:java.time
Clases de Java 8Me he tomado la libertad de cambiar el tipo de su campo de instancia de
Date
aInstant
, la clase correspondiente en Java 8. Prometo volver al tratamiento deDate
abajo. También he agregado una zona horaria constante. Puede establecerlo enZoneOffset.UTC
oZoneId.of("Europe/Stockholm")
lo que considere apropiado (establecerlo en unZoneOffset
trabajo porqueZoneOffset
es una subclase deZoneId
).Elegí mostrar la solución usando las clases de Java 8. Pediste la forma más sencilla, ¿verdad? :-) Aquí está el
compareTo
método que solicitó:Si nunca necesita la pieza del tiempo de
when
, por supuesto, es más fácil para declararwhen
unaLocalDate
y saltar todas las conversiones. Entonces tampoco tenemos que preocuparnos por la zona horaria.Ahora suponga que por alguna razón no puede declarar su
when
campoInstant
o desea mantenerlo a la antiguaDate
. Si aún puede usar Java 8, simplemente conviértaloInstant
, luego haga lo que hizo antes:Del mismo modo para
o.when
.No Java 8?
Si no puede usar Java 8, hay dos opciones:
Calendar
oSimpleDateFormat
.Las formas anticuadas
La respuesta de Adamski le muestra cómo quitar la parte del tiempo de
Date
usar laCalendar
clase. Le sugiero que utilicegetInstance(TimeZone)
para obtener laCalendar
instancia para la zona horaria que desee. Como alternativa, puede usar la idea de la segunda mitad de la respuesta de Jorn .Usar
SimpleDateFormat
es realmente una forma indirecta de usarCalendar
ya que aSimpleDateFormat
contiene unCalendar
objeto. Sin embargo, puede encontrarlo menos problemático que usarloCalendar
directamente:Esto fue inspirado por la respuesta de Rob .
Dependencia de zona horaria
¿Por qué tenemos que elegir una zona horaria específica? Digamos que queremos comparar dos veces que en UTC son 24 de marzo 0:00 (medianoche) y 12:00 (mediodía). Si hace eso en CET (digamos, Europa / París), son las 1 am y la 1 pm el 24 de marzo, es decir, la misma fecha. En Nueva York (hora de verano del este), son las 20:00 el 23 de marzo y las 8:00 el 24 de marzo, es decir, no es la misma fecha. Por lo tanto, hace una diferencia la zona horaria que elija. Si solo confía en el valor predeterminado de la computadora, puede encontrarse con sorpresas cuando alguien intenta ejecutar su código en una computadora en otro lugar de este mundo globalizado.
Enlace
Enlace a ThreeTen Backport, el backport de las clases de fecha y hora de Java 8 a Java 6 y 7: http://www.threeten.org/threetenbp/ .
fuente
Mi propuesta:
fuente
Usando Apache commons puedes hacer:
fuente
Esta es la forma más sencilla de resolver este problema.
fuente
Resolví esto comparando por marca de tiempo:
Evito usar Joda Time porque en Android usa un gran espacio. El tamaño importa. ;)
fuente
Otra solución que usa Java 8 e Instant, es usar el método truncatedTo
Ejemplo:
fuente
fuente
Esto es lo que funcionó para mí:
fuente
¿Qué tal
DateUtil.daysBetween()
. Es Java y devuelve un número (diferencia en días).fuente