Comparing Dates in Java

1. Introduction

In this tutorial, we’ll focus on how to compare dates using the Java 8 Date/Time API. We’ll dive into different methods to check whether two dates are equal and how to compare dates.

2. Comparing Dates

The basic way to express a date in Java is LocalDate. Let’s consider two LocalDate object instances, representing the 10th of August 2019 and the 1st of July 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().

We use the isAfter() method to check if the date instance is after the other specified date. Therefore, the next JUnit assertion will pass:

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

Analogously, the method isBefore() checks if the date instance is before the other specified date:

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

The method isEqual() checks if a date represents the same point on the local timeline as the other specified date:

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

2.1. Comparing Dates Using the Comparable Interface

The equals() method will give the same result as isEqual(), but only if the argument passed is of the same type (in this case, LocalDate):

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

The isEqual() method can be used instead to compare with objects of a different type, such as JapaneseDateThaiBuddhistDate, etc.

We can compare two date instances by using the compareTo() method, as defined by the Comparable interface:

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

3. Comparing Date Instances Containing the Time Component

This section will explain how to compare two LocalDateTime instances. LocalDateTime instances contain the date as well as the time component.

Similarly to LocalDate, we’re comparing two LocalDateTime instances with the methods isAfter()isBefore() and isEqual(). Additionally, equals() and compareTo() can be used in a similar fashion as described for LocalDate.

Likewise, we can use the same methods for comparing two ZonedDateTime instances. Let’s compare 8:00 local time in New York and 14:00 local time in Berlin, on the same day:

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));

Although both ZonedDateTime instances represent the same moment in time, they do not represent equal Java objects. They have different LocalDateTime and ZoneId fields internally:

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

4. Additional Comparisons

Let’s create a simple utility class for slightly more complex comparisons.

Firstly, we’ll check if instances of LocalDateTime and LocalDate are on the same day:

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

Secondly, we’ll check if two instances of LocalDateTime are on the same day:

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, which in our example is a day.

Thirdly, we can implement a comparison at the level of an hour:

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

Finally, in a similar way, we can check if two ZonedDateTime instances happen within the same hour:

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

We can see that two ZonedDateTime objects are actually happening within the same hour, even if their local times are different (8:30 and 14:00, respectively):

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. Comparison in the Old Java Date API

Before Java 8, we had to use java.util.Date and java.util.Calendar classes for manipulating date/time information. The design of the old Java Date API has many flaws, such as being complex and not thread-safe. The java.util.Date instance represents an “instant in time” and not a real date.

One of the solutions was to use the Joda Time library. Since the release of Java 8, it is recommended to migrate 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. The dates are compared as the instants in time, on the level of a millisecond:

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));

For more complex comparisons, we can use DateUtils from the Apache Commons Lang library. This class contains many handy methods for dealing with Date and Calendar objects:

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. We can find more details in our Convert Date to LocalDate or LocalDateTime and Back tutorial.

6. Conclusion

In this article, we’ve explored different ways of comparing date instances in Java.

The Java 8 Date/Time classes have rich APIs for comparing dates, with or without time and time zones. We’ve also seen how to compare dates on the granularity of a day, hour, minute, etc.

All of the code snippets mentioned in the article, including additional examples, are available over on GitHub.

Related posts:

Spring Boot - OAuth2 with JWT
Java Program to Check Whether a Directed Graph Contains a Eulerian Cycle
Guide to BufferedReader
Java Program to Implement Branch and Bound Method to Perform a Combinatorial Search
Java Program to Implement Disjoint Sets
Spring REST API + OAuth2 + Angular
Java Program to Sort an Array of 10 Elements Using Heap Sort Algorithm
Java Program to Implement ConcurrentHashMap API
Java Program to Implement PriorityBlockingQueue API
Java Program to Describe the Representation of Graph using Adjacency Matrix
A Quick Guide to Using Keycloak with Spring Boot
Java Program to Implement Max Heap
Java Program to Implement ArrayList API
Java Program to Solve the Fractional Knapsack Problem
Java Program to Implement Fibonacci Heap
Java Program to Implement Cartesian Tree
Java 8 Stream API Analogies in Kotlin
Java Program to Implement Patricia Trie
Spring REST API with Protocol Buffers
Receive email by java client
Java Program to Check if any Graph is Possible to be Constructed for a Given Degree Sequence
Java Program to Implement Gale Shapley Algorithm
Java Program to Implement SynchronosQueue API
Guide to Selenium with JUnit / TestNG
How to Set TLS Version in Apache HttpClient
Java Program to Implement the Alexander Bogomolny’s UnOrdered Permutation Algorithm for Elements Fro...
Removing all duplicates from a List in Java
Lập trình đa luồng với CompletableFuture trong Java 8
Merging Two Maps with Java 8
Java Program to Construct an Expression Tree for an Postfix Expression
Introduction to Spring Data JDBC
Zipping Collections in Java