Comparando dos java.util.Dates para ver si están en el mismo día

Necesito comparar dos Date (por ejemplo, date1 y date2 ) y presentar un boolean sameDay mismo día, que es cierto para las dos Date compartidas el mismo día, y falso si no lo son.

¿Cómo puedo hacer esto? Parece que hay un torbellino de confusión aquí … y me gustaría evitar tirar de otras dependencias más allá del JDK si es posible.

para aclarar: si date1 y date2 comparten el mismo año, mes y día, entonces sameDay es verdadero; de lo contrario, es falso. Me doy cuenta de que esto requiere conocimiento de una zona horaria … sería agradable pasar en una zona horaria, pero puedo vivir con GMT o con la hora local, siempre que sepa cuál es el comportamiento.

de nuevo, para aclarar:

 date1 = 2008 Jun 03 12:56:03 date2 = 2008 Jun 03 12:59:44 => sameDate = true date1 = 2009 Jun 03 12:56:03 date2 = 2008 Jun 03 12:59:44 => sameDate = false date1 = 2008 Aug 03 12:00:00 date2 = 2008 Jun 03 12:00:00 => sameDate = false 

 Calendar cal1 = Calendar.getInstance(); Calendar cal2 = Calendar.getInstance(); cal1.setTime(date1); cal2.setTime(date2); boolean sameDay = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR); 

Tenga en cuenta que “el mismo día” no es un concepto tan simple como suena cuando se pueden involucrar diferentes zonas horarias. El código anterior para ambas fechas calculará el día relativo a la zona horaria utilizada por la computadora en la que se está ejecutando. Si esto no es lo que necesita, debe pasar la (s) zona (s) horaria (s) correspondiente (s) a las llamadas de Calendar.getInstance() , una vez que haya decidido qué quiere decir exactamente con “el mismo día”.

Y sí, el LocalDate Joda Time lo haría todo mucho más limpio y fácil (aunque las mismas dificultades relacionadas con las zonas horarias estarían presentes).

Qué tal si:

 SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd"); return fmt.format(date1).equals(fmt.format(date2)); 

También puede establecer la zona horaria en SimpleDateFormat, si es necesario.

Yo uso el paquete “apache commons lang” para hacer esto (es decir, org.apache.commons.lang.time.DateUtils)

 boolean samedate = DateUtils.isSameDay(date1, date2); //Takes either Calendar or Date objects 

Puede evitar las dependencias externas y el impacto en el rendimiento de usar el calendario calculando el número del día juliano para cada una de las fechas y luego compararlas:

 public static boolean isSameDay(Date date1, Date date2) { // Strip out the time part of each date. long julianDayNumber1 = date1.getTime() / MILLIS_PER_DAY; long julianDayNumber2 = date2.getTime() / MILLIS_PER_DAY; // If they now are equal then it is the same day. return julianDayNumber1 == julianDayNumber2; } 

Joda-Time

En cuanto a agregar una dependencia, me temo que java.util.Date & .Calendar realmente son tan malos que lo primero que hago para cualquier proyecto nuevo es agregar la biblioteca Joda-Time. En Java 8 puedes usar el nuevo paquete java.time, inspirado en Joda-Time.

El núcleo de Joda-Time es la clase DateTime . A diferencia de java.util.Date, entiende su zona horaria asignada ( DateTimeZone ). Al convertir JuDate, asigne una zona.

 DateTimeZone zone = DateTimeZone.forID( "America/Montreal" ); DateTime dateTimeQuébec = new DateTime( date , zone ); 

LocalDate

Una forma de verificar si dos fechas-fechas aterrizan en la misma fecha es convertir a objetos LocalDate .

Esa conversión depende de la zona horaria asignada. Para comparar objetos LocalDate , deben haberse convertido con la misma zona.

Aquí hay un pequeño método de utilidad.

 static public Boolean sameDate ( DateTime dt1 , DateTime dt2 ) { LocalDate ld1 = new LocalDate( dt1 ); // LocalDate determination depends on the time zone. // So be sure the date-time values are adjusted to the same time zone. LocalDate ld2 = new LocalDate( dt2.withZone( dt1.getZone() ) ); Boolean match = ld1.equals( ld2 ); return match; } 

Mejor sería otro argumento, especificar el huso horario en lugar de asumir que se debe usar el primer huso horario del objeto DateTime.

 static public Boolean sameDate ( DateTimeZone zone , DateTime dt1 , DateTime dt2 ) { LocalDate ld1 = new LocalDate( dt1.withZone( zone ) ); // LocalDate determination depends on the time zone. // So be sure the date-time values are adjusted to the same time zone. LocalDate ld2 = new LocalDate( dt2.withZone( zone ) ); return ld1.equals( ld2 ); } 

Representación de cadena

Otro enfoque es crear una representación de cadena de la porción de fecha de cada fecha y hora, luego comparar cadenas.

De nuevo, la zona horaria asignada es crucial.

 DateTimeFormatter formatter = ISODateTimeFormat.date(); // Static method. String s1 = formatter.print( dateTime1 ); String s2 = formatter.print( dateTime2.withZone( dt1.getZone() ) ); Boolean match = s1.equals( s2 ); return match; 

Lapso de tiempo

La solución generalizada es definir un lapso de tiempo, luego pregunte si el lapso contiene su objective. Este código de ejemplo está en Joda-Time 2.4. Tenga en cuenta que las clases relacionadas con “medianoche” están en desuso. En su lugar, use el método withTimeAtStartOfDay . Joda-Time ofrece tres clases para representar un lapso de tiempo de varias maneras: intervalo, período y duración.

Usando el enfoque “Medio Abierto” donde el comienzo del tramo es inclusivo y el final exclusivo.

La zona horaria del objective puede ser diferente a la zona horaria del intervalo.

 DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ); DateTime target = new DateTime( 2012, 3, 4, 5, 6, 7, timeZone ); DateTime start = DateTime.now( timeZone ).withTimeAtStartOfDay(); DateTime stop = start.plusDays( 1 ).withTimeAtStartOfDay(); Interval interval = new Interval( start, stop ); boolean containsTarget = interval.contains( target ); 

java.time

Java 8 y versiones posteriores vienen con el framework java.time . Inspirado por Joda-Time, definido por JSR 310, y extendido por el proyecto ThreeTen-Extra. Ver Tutorial .

Los creadores de Joda-Time nos han instruido a todos a pasar a java.time tan pronto como sea conveniente. Mientras tanto, Joda-Time continúa como un proyecto activamente mantenido. Pero espere que el trabajo futuro ocurra solo en java.time y ThreeTen-Extra en lugar de Joda-Time.

Para resumir java.time en pocas palabras … Un Instant es un momento en la línea de tiempo en UTC. Aplique una zona horaria ( ZoneId ) para obtener un objeto ZonedDateTime . Para salir de la línea de tiempo, para obtener la vaga idea indefinida de una fecha y hora, use las clases “locales”: LocalDateTime , LocalDate , LocalTime .

La lógica discutida en la sección Joda-Time de esta respuesta se aplica a java.time.

La antigua clase java.util.Date tiene un nuevo método toInstant para la conversión a java.time.

 Instant instant = yourJavaUtilDate.toInstant(); // Convert into java.time type. 

La determinación de una fecha requiere un huso horario.

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); 

Aplicamos ese objeto de zona horaria al Instant para obtener un ZonedDateTime . De eso extraemos un valor de solo la fecha (un LocalDate ) ya que nuestro objective es comparar fechas (no horas, minutos, etc.).

 ZonedDateTime zdt1 = ZonedDateTime.ofInstant( instant , zoneId ); LocalDate localDate1 = LocalDate.from( zdt1 ); 

Haz lo mismo con el segundo objeto java.util.Date que necesitamos para comparar. Usaré el momento actual en su lugar.

 ZonedDateTime zdt2 = ZonedDateTime.now( zoneId ); LocalDate localDate2 = LocalDate.from( zdt2 ); 

Use el método especial isEqual para probar el mismo valor de fecha.

 Boolean sameDate = localDate1.isEqual( localDate2 ); 

Convierta fechas a Java 8 java.time.LocalDate como se ve aquí .

 LocalDate localDate1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); LocalDate localDate2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); // compare dates assertTrue("Not on the same day", localDate1.equals(localDate2)); 
 private boolean isSameDay(Date date1, Date date2) { Calendar calendar1 = Calendar.getInstance(); calendar1.setTime(date1); Calendar calendar2 = Calendar.getInstance(); calendar2.setTime(date2); boolean sameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR); boolean sameMonth = calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH); boolean sameDay = calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH); return (sameDay && sameMonth && sameYear); } 

Java 8

Si usa Java 8 en su proyecto y compara java.sql.Timestamp , puede usar la clase LocalDate :

 sameDate = date1.toLocalDateTime().toLocalDate().equals(date2.toLocalDateTime().toLocalDate()); 

Si está usando java.util.Date , eche un vistazo a la respuesta de Istvan que es menos ambigua.

PARA USUARIOS ANDROIDES:

Puede usar DateUtils.isToday(dateMilliseconds) para verificar si la fecha dada es el día actual o no.

Referencia de API: https://developer.android.com/reference/android/text/format/DateUtils.html#isToday(long)

además de la solución de Binil Thomas

 public static boolean isOnSameDay(Timestamp... dates) { SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd"); String date1 = fmt.format(dates[0]); for (Timestamp date : dates) { if (!fmt.format(date).equals(date1)) { return false; } } return true; } 

uso

  isOnSameDay(date1,date2,date3 ...); //or isOnSameDay(mydates); 
 public static boolean validSearchRange(String start, String end){ SimpleDateFormat dateFormat = new SimpleDateFormat(clientDateFormat); try { Date start_date = dateFormat.parse(start); Date end_date = dateFormat.parse(end); return !start_date.after(end_date); } catch (ParseException e) { e.printStackTrace(); } return false; } 

puede aplicar la misma lógica que la solución SimpleDateFormat sin depender de SimpleDateFormat

 date1.getFullYear()*10000 + date1.getMonth()*100 + date1.getDate() == date2.getFullYear()*10000 + date2.getMonth()*100 + date2.getDate()