Comparación de fechas en Java

1. Introducción

En este tutorial, nos centraremos en cómo comparar fechas utilizando la API de fecha / hora de Java 8. Nos sumergiremos en diferentes métodos para comprobar si dos fechas son iguales y cómo compararlas.

2. Comparación de fechas

La forma básica de expresar una fecha en Java es LocalDate . Consideremos dos instancias de objetos LocalDate , que representan el 10 de agosto de 2019 y el 1 de julio de 2019:

LocalDate firstDate = LocalDate.of(2019, 8, 10); LocalDate secondDate = LocalDate.of(2019, 7, 1);

Vamos a comparar dos objetos LocalDate utilizando los métodos isAfter () , isBefore () e isEqual (), así como equals () y compareTo () .

Usamos el método isAfter () para verificar si la instancia de fecha es posterior a la otra fecha especificada. Por lo tanto, la siguiente aserción JUnit pasará:

assertThat(firstDate.isAfter(secondDate), is(true));

De forma análoga, el método isBefore () comprueba si la instancia de fecha es anterior a la otra fecha especificada:

assertThat(firstDate.isBefore(secondDate), is(false));

El método isEqual () comprueba si una fecha representa el mismo punto en la línea de tiempo local que la otra fecha especificada:

assertThat(firstDate.isEqual(firstDate), is(true)); assertThat(firstDate.isEqual(secondDate), is(false));

2.1. Comparación de fechas con la interfaz comparable

El método equals () dará el mismo resultado que isEqual () , pero solo si el argumento pasado es del mismo tipo (en este caso, LocalDate ):

assertThat(firstDate.equals(secondDate), is(false));

El método isEqual () se puede utilizar en su lugar para comparar con objetos de un tipo diferente, como JapaneseDate , ThaiBuddhistDate , etc.

Podemos comparar dos instancias de fecha utilizando el método compareTo () , según lo definido por la interfaz Comparable :

assertThat(firstDate.compareTo(secondDate), is(1)); assertThat(secondDate.compareTo(firstDate), is(-1));

3. Comparación de instancias de fecha que contienen el componente de hora

Esta sección explica cómo comparar dos instancias de LocalDateTime . Las instancias de LocalDateTime contienen la fecha y el componente de hora.

De manera similar a LocalDate , estamos comparando dos instancias de LocalDateTime con los métodos isAfter () , isBefore () e isEqual () . Además, equals () y compareTo () se pueden usar de manera similar a la descrita para LocalDate.

Del mismo modo, podemos usar los mismos métodos para comparar dos instancias de ZonedDateTime . Comparemos las 8:00 hora local en Nueva York y las 14:00 hora local en Berlín, el mismo día:

ZonedDateTime timeInNewYork = ZonedDateTime.of(2019, 8, 10, 8, 0, 0, 0, ZoneId.of("America/New_York")); ZonedDateTime timeInBerlin = ZonedDateTime.of(2019, 8, 10, 14, 0, 0, 0, ZoneId.of("Europe/Berlin")); assertThat(timeInNewYork.isAfter(timeInBerlin), is(false)); assertThat(timeInNewYork.isBefore(timeInBerlin), is(false)); assertThat(timeInNewYork.isEqual(timeInBerlin), is(true));

Aunque ambas instancias de ZonedDateTime representan el mismo momento en el tiempo, no representan objetos Java iguales. Tienen diferentes campos LocalDateTime y ZoneId internamente:

assertThat(timeInNewYork.equals(timeInBerlin), is(false)); assertThat(timeInNewYork.compareTo(timeInBerlin), is(-1));

4. Comparaciones adicionales

Creemos una clase de utilidad simple para comparaciones un poco más complejas.

En primer lugar, comprobaremos si las instancias de LocalDateTime y LocalDate están en el mismo día:

public static boolean isSameDay(LocalDateTime timestamp, LocalDate localDateToCompare) { return timestamp.toLocalDate().isEqual(localDateToCompare); }

En segundo lugar, comprobaremos si dos instancias de LocalDateTime están en el mismo día:

public static boolean isSameDay(LocalDateTime timestamp, LocalDateTime timestampToCompare) { return timestamp.truncatedTo(DAYS) .isEqual(timestampToCompare.truncatedTo(DAYS)); }

El método truncatedTo (TemporalUnit) trunca una fecha en el nivel dado , que en nuestro ejemplo es un día.

En tercer lugar, podemos implementar una comparación a nivel de una hora:

public static boolean isSameHour(LocalDateTime timestamp, LocalDateTime timestampToCompare) { return timestamp.truncatedTo(HOURS) .isEqual(timestampToCompare.truncatedTo(HOURS)); }

Finalmente, de manera similar, podemos verificar si dos instancias ZonedDateTime ocurren dentro de la misma hora:

public static boolean isSameHour(ZonedDateTime zonedTimestamp, ZonedDateTime zonedTimestampToCompare) { return zonedTimestamp.truncatedTo(HOURS) .isEqual(zonedTimestampToCompare.truncatedTo(HOURS)); }

Podemos ver que dos objetos ZonedDateTime en realidad están sucediendo dentro de la misma hora, incluso si sus horas locales son diferentes (8:30 y 14:00, respectivamente):

ZonedDateTime zonedTimestamp = ZonedDateTime.of(2019, 8, 10, 8, 30, 0, 0, ZoneId.of("America/New_York")); ZonedDateTime zonedTimestampToCompare = ZonedDateTime.of(2019, 8, 10, 14, 0, 0, 0, ZoneId.of("Europe/Berlin")); assertThat(DateTimeComparisonUtils. isSameHour(zonedTimestamp, zonedTimestampToCompare), is(true));

5. Comparación en la API de fecha antigua de Java

Antes de Java 8, teníamos que usar las clases java.util.Date y java.util.Calendar para manipular la información de fecha / hora. El diseño de la antigua API de Java Date tiene muchos defectos, como ser complejo y no seguro para subprocesos. La instancia java.util.Date representa un "instante en el tiempo" y no una fecha real.

Una de las soluciones fue utilizar la biblioteca Joda Time. Desde el lanzamiento de Java 8, se recomienda migrar a la API de fecha / hora de Java 8.

De manera similar a LocalDate y LocalDateTime , los objetos java.util.Date y java.util.Calendar tienen métodos after () , before () , compareTo () y equals () para comparar dos instancias de fecha . Las fechas se comparan como instantes en el tiempo, al nivel de un milisegundo:

Date firstDate = toDate(LocalDateTime.of(2019, 8, 10, 0, 00, 00)); Date secondDate = toDate(LocalDateTime.of(2019, 8, 15, 0, 00, 00)); assertThat(firstDate.after(secondDate), is(false)); assertThat(firstDate.before(secondDate), is(true)); assertThat(firstDate.compareTo(secondDate), is(-1)); assertThat(firstDate.equals(secondDate), is(false));

Para comparaciones más complejas, podemos usar DateUtils de la biblioteca Apache Commons Lang. Esta clase contiene muchos métodos útiles para tratar con objetos de fecha y calendario :

public static boolean isSameDay(Date date, Date dateToCompare) { return DateUtils.isSameDay(date, dateToCompare); } public static boolean isSameHour(Date date, Date dateToCompare) { return DateUtils.truncatedEquals(date, dateToCompare, Calendar.HOUR); }

Para comparar los objetos de fecha que se originan en las diferentes API, primero debemos hacer una conversión adecuada y solo luego aplicar la comparación. Podemos encontrar más detalles en nuestro tutorial Convertir fecha a LocalDate o LocalDateTime y retroceder.

6. Conclusión

En este artículo, exploramos diferentes formas de comparar instancias de fecha en Java.

Las clases de fecha / hora de Java 8 tienen API completas para comparar fechas, con o sin zonas horarias y horarias. También hemos visto cómo comparar fechas según la granularidad de un día, hora, minuto, etc.

Todos los fragmentos de código mencionados en el artículo, incluidos ejemplos adicionales, están disponibles en GitHub.