Comparando datas em Java
1. Introdução
Neste tutorial, vamos nos concentrar em como comparar datas usandoJava 8 Date/Time API. Vamos mergulhar em métodos diferentes para verificar se duas datas são iguais e como comparar datas.
2. Comparando datas
A maneira básica de expressar uma data em Java éLocalDate. Vamos considerar duas instâncias de objetoLocalDate, representando 10 de agosto de 2019 e 1 de julho de 2019:
LocalDate firstDate = LocalDate.of(2019, 8, 10);
LocalDate secondDate = LocalDate.of(2019, 7, 1);
We’re going to compare two LocalDate objects by utilizing the isAfter(), isBefore(), and isEqual() methods, as well as equals() and compareTo().
Usamos o métodoisAfter() para verificar se a instância da data é posterior à outra data especificada. Portanto, a próxima asserção JUnit será aprovada:
assertThat(firstDate.isAfter(secondDate), is(true));
Analogamente, o métodoisBefore() verifica se a instância de data é anterior à outra data especificada:
assertThat(firstDate.isBefore(secondDate), is(false));
O métodoisEqual() verifica se uma data representa o mesmo ponto na linha do tempo local que a outra data especificada:
assertThat(firstDate.isEqual(firstDate), is(true));
assertThat(firstDate.isEqual(secondDate), is(false));
2.1. Comparando datas usando a interfaceComparable
O métodoequals() dará o mesmo resultado queisEqual(), mas apenas se o argumento passado for do mesmo tipo (neste caso,LocalDate):
assertThat(firstDate.equals(secondDate), is(false));
O métodoisEqual() pode ser usado em vez de comparar com objetos de um tipo diferente, comoJapaneseDate,ThaiBuddhistDate, etc.
Podemos comparar duas instâncias de data usando o métodocompareTo(), conforme definido pela interfaceComparable:
assertThat(firstDate.compareTo(secondDate), is(1));
assertThat(secondDate.compareTo(firstDate), is(-1));
3. Comparando instâncias de data que contêm o componente de hora
Esta seção explicará como comparar duas instâncias deLocalDateTime. As instânciasLocalDateTime contêm a data, bem como o componente de tempo.
Similarly to LocalDate, we’re comparing two LocalDateTime instances with the methods isAfter(), isBefore() and isEqual(). Além disso,equals() ecompareTo() podem ser usados de maneira semelhante à descrita paraLocalDate.
Da mesma forma, podemos usar os mesmos métodos para comparar duas instâncias deZonedDateTime. Vamos comparar as 8:00 hora local em Nova York e 14:00 hora local em Berlim, no mesmo dia:
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));
Embora ambas as instânciasZonedDateTime representem o mesmo momento no tempo, elas não representam objetos Java iguais. Eles têm camposLocalDateTimeeZoneId diferentes internamente:
assertThat(timeInNewYork.equals(timeInBerlin), is(false));
assertThat(timeInNewYork.compareTo(timeInBerlin), is(-1));
4. Comparações adicionais
Vamos criar uma classe de utilitário simples para comparações um pouco mais complexas.
Em primeiro lugar, vamos verificar se as instâncias deLocalDateTime eLocalDate estão no mesmo dia:
public static boolean isSameDay(LocalDateTime timestamp,
LocalDate localDateToCompare) {
return timestamp.toLocalDate().isEqual(localDateToCompare);
}
Em segundo lugar, vamos verificar se duas instâncias deLocalDateTime estão no mesmo dia:
public static boolean isSameDay(LocalDateTime timestamp,
LocalDateTime timestampToCompare) {
return timestamp.truncatedTo(DAYS)
.isEqual(timestampToCompare.truncatedTo(DAYS));
}
The truncatedTo(TemporalUnit) method truncates a date on the given level, que em nosso exemplo é um dia.
Em terceiro lugar, podemos implementar uma comparação no nível de uma hora:
public static boolean isSameHour(LocalDateTime timestamp,
LocalDateTime timestampToCompare) {
return timestamp.truncatedTo(HOURS)
.isEqual(timestampToCompare.truncatedTo(HOURS));
}
Finalmente, de forma semelhante, podemos verificar se duas instâncias deZonedDateTime acontecem na mesma hora:
public static boolean isSameHour(ZonedDateTime zonedTimestamp,
ZonedDateTime zonedTimestampToCompare) {
return zonedTimestamp.truncatedTo(HOURS)
.isEqual(zonedTimestampToCompare.truncatedTo(HOURS));
}
Podemos ver que dois objetosZonedDateTime estão realmente acontecendo na mesma hora, mesmo que seus horários locais sejam diferentes (8:30 e 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. Comparação na antiga API de data do Java
Antes do Java 8, tínhamos que usar as classesjava.util.Dateejava.util.Calendar para manipular informações de data / hora. O design da antiga API Java Date tem muitas falhas, como ser complexo e não ser seguro para threads. A instânciajava.util.Date representa um “instante no tempo” e não uma data real.
Uma das soluções foi usar a bibliotecaJoda Time. Desde o lançamento do Java 8, é recomendado paramigrate to the Java 8 Date/Time API.
Similarly to LocalDate and LocalDateTime, both java.util.Date and java.util.Calendar objects have after(), before(), compareTo() and equals() methods for comparing two date instances. As datas são comparadas como os instantes no tempo, no nível de um milissegundo:
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 comparações mais complexas, podemos usarDateUtils da bibliotecaApache Commons Lang. Esta classe contém muitos métodos úteis para lidar com objetosDateeCalendar:
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);
}
To compare date objects originating from the different APIs, we should first do a proper conversion and only then apply the comparison. Podemos encontrar mais detalhes em nosso tutorialConvert Date to LocalDate or LocalDateTime and Back.
6. Conclusão
Neste artigo, exploramos diferentes maneiras de comparar instâncias de data em Java.
As classes Java 8 Date / Time possuem APIs avançadas para comparar datas, com ou sem fuso horário e fuso horário. Também vimos como comparar datas na granularidade de um dia, hora, minuto, etc.
Todos os trechos de código mencionados no artigo, incluindo exemplos adicionais, estão disponíveisover on GitHub.