How to Compare Dates in Java - Stack Abuse

How to Compare Dates in Java

Introduction

Dates are something we encounter in everyday life, whether they're used for calendars, scheduling appointments, or even remembering birthdays. Naturally, when working with dates we will often need to know if a certain date comes before or after another, or if they represent the same calendar date.

In this article, we'll take a look at how to compare two dates in Java.

Comparing Dates

The java.util.Date class represents a specific instant in time with millisecond precision.

It also has several built-in methods that allow us to compare each Date instance with other Date instances:

  • Date.compareTo(Date date)
  • Date.equals(Object obj)
  • Date.before(Date when)
  • Date.after(Date when)

Note: Please note that the Date class has several deprecated methods, including the regular constructor. It's an old class, replaced with the new Date/Time API in Java 8, covered right after this section. If you're using Java 8+, please refer to the sections after this.

If you're using a version prior to Java 8, please refer to the Joda-Time Section.

Using Date.compareTo()

As usual with compareTo() methods implemented from the Comparable interface, this method accepts another Date argument and compares it to the value of the invoking Date, returning 0 if the values are equal, a value less than 0 if the invoking date is before the argument, and a value greater than 0 if the invoking date is after the argument.

Otherwise, it throws a NullPointerException, if the argument is null.

Let's instantiate two Date objects, and compare them:

Date date1 = new Date(2020, 1, 1);
Date date2 = new Date(2020, 1, 1);
int result = date1.compareTo(date2);

if(result == 0)
    System.out.println("Both dates are equal");
else if (result < 0)
	System.out.println("Date1 is before Date2");
else
	System.out.println("Date1 is after Date2");

Running this code results in:

Both dates are equal

Note: Again, this only works for Java versions prior to Java 8. Since, the Date(int year, int month, int day) constructor has been deprecated, and only Date(long date) still stands.

Using Date.before(), Date.after(), and Date.equals()

The after() method tests if the invoking Date is after the argument Date object, returning true or false values respectively. before() does the same, though, checks if the invoking Date is before the argument Date.

The equals() method compares two Dates for equality and returns true if and only if the argument is not null and is a Date object that represents the same point in time as the invoking object, else it will return false. In other words, it checks if the references point to the same object in memory.

All three throw a NullPointerException if the argument is null. Now, we can make the previous code snippet more user-friendly and readable, if we replace the integer checks with these methods:

SimpleDateFormat formatter = new SimpleDateFormat("YYYY-MM-dd");
Date date1 = new Date(); // Returns the current date and time
Date date2 = new Date(2021, 2, 12);
        
String formatted1 = formatter.format(date1);
String formatted2 = formatter.format(date2);

if(date1.equals(date2))
    System.out.println("Both dates are equal");
else if(date1.after(date2))
    System.out.println(String.format("%s comes after %s", formatted1, formatted2));
else if(date1.before(date2))
    System.out.println(String.format("%s comes before %s", formatted1, formatted2));

If you're unfamiliar with the SimpleDateFormat class, you can read our Guide on Formatting Dates in Java with SimpleDateFormat

Running this code results in:

2021-03-24 comes after 2021-02-12

Comparing LocalDates

As of Java 8, we had some big changes regarding date and time. There were many issues with the existing date and time API, such as the lack of thread-safe classes and methods, lack of timezone logic, and the overall API design wasn't very easy to understand.

Lead by these issues, the author of Joda-Time (a popular substitute for the lackluster API prior to Java 8) and Oracle, presented us the new Date/Time API through java.time.

LocalDate class is one of the most commonly used classes of java.time, alongside LocalTime and LocalDateTime. It represents date without time or time zone fields with a default date format of yyyy-mm-dd.

The built-in methods for comparison are pretty similar to the Date class:

  • LocalDate.isAfter()
  • LocalDate.isBefore()
  • LocalDate.isEqual()
  • LocalDate.compareTo()
  • LocalDate.equals()

Using LocalDate.isAfter(), LocalDate.isBefore(), and LocalDate.isEqual()

All three methods check if the invoked LocalDate is before, after, or equal to the argument, returning boolean values respectively.

Let's instantiate two LocalDate instances, using the helper method of(), and passing in the year, month and day values:

LocalDate date1 = LocalDate.of(2020, 3, 25);
LocalDate date2 = LocalDate.of(2020, 7, 29);

if (date1.isAfter(date2))
    System.out.println(String.format("%s comes after %s", date1, date2));
else if (date1.isBefore(date2))
    System.out.println(String.format("%s comes before %s", date1, date2));
else if (date1.isEqual(date2))
    System.out.println("Both dates are equal");

This results in:

2020-03-25 comes before 2020-07-29

Using LocalDate.compareTo() and LocalDate.equals()

Git Essentials

Check out this hands-on, practical guide to learning Git, with best-practices and industry-accepted standards. Stop Googling Git commands and actually learn it!

Again, as usual, compareTo() compares instances and returns -1, 0, or 1 depending on the values of the LocalDates. On the other hand, the equals() method checks if the references point to the same object in memory:

LocalDate date1 = LocalDate.of(2021, 12, 12);
LocalDate date2 = LocalDate.of(2021, 12, 12);
    
if(date1.equals(date2)) {
    System.out.println("Same LocalDate");
} else if(date1.compareTo(date2) > 0) {
    System.out.println(String.format("%s is after %s", date1, date2));
} else if(date1.compareTo(date2) < 0) {
    System.out.println(String.format("%s is before %s", date1, date2));
} else {
    System.out.println(String.format("%s and %s represent the same date", date1, date2));
}

Since we've created two LocalDates with the same values, without using the new keyword that ensures a new Object, these are the same LocalDate:

Same LocalDate

In fact, since LocalDate doesn't have a public constructor, we can't really ever call new on it.

Comparing Calendars

The java.util.Calendar class is a part of the old Date/Time API, and is mainly used for conversion between instants and calendar fields, such as DAY_OF_MONTH, etc.

They can also hold date-related data, and of course, they can be compared:

Calendar c1 = Calendar.getInstance();
c1.set(2020, Calendar.AUGUST, 15);
Calendar c2 = Calendar.getInstance();
c2.set(2020, Calendar.JULY, 4);

if(c1.equals(c2))
    System.out.println("Calendars are equal");
else if(c1.after(c2))
    System.out.println(c1.getTime() + " comes after " + c1.getTime());
else if(c1.before(c2))
    System.out.println(c1.getTime() + " comes before " + c2.getTime());

This results in:

Sat Aug 15 14:22:24 UTC 2020 comes after Sat Aug 15 14:22:24 UTC 2020

Comparing With Joda-Time

Joda-Time was the standardized third-party Date/Time library for Java, prior to Java 8. It addressed the issues present in the original API, which there were plenty of. It also served as an inspiration and starting point to overhaul the whole API, which resulted in the current java.time package.

With Joda-Time we can use up to eight different calendar systems, manipulate time zones, or even define our own custom calendars. But more importantly, we don't have to worry about mutability.

Rather than representing dates as instances in time, Joda-Time represents them as actual dates. To show how we compare dates using Joda-Time, we'll be using LocalDate class (Joda-Time class) which is thread-safe.

Using DateTimeComparator

The DateTimeComparator class is specifically made to compare dates. It works with ReadableInstants, Strings, Dates, Calendars and Longs. So, we'll have to convert our Joda-Time LocalDates, to Dates:

LocalDate date1 = new LocalDate(2021, 11, 11);
LocalDate date2 = new LocalDate(2021, 12, 12);

int result = DateTimeComparator.getInstance()
             .compare(date1.toDate(), date2.toDate());
System.out.println(result);

This method returns an integer result, just like the compareTo() method, where -1 means the first date is before the second, 0 means they're the same, and 1 means that the first object is after the second:

-1

Using LocalDate.isEqual()

In a similar vein to the current Date/Time API, we can use isEqual():

LocalDate date1 = new LocalDate(2021, 11, 11);
LocalDate date2 = new LocalDate(2021, 12, 12);

System.out.println(date1.isEqual(date2));

This results in a boolean:

false

Using LocalDate.isBefore() and LocalDate.isAfter()

Again, much like the Java 8 API, we can use the isBefore() and isAfter() methods to compare two LocalDates:

LocalDate date1 = new LocalDate(2021, 11, 11);
LocalDate date2 = new LocalDate(2021, 12, 12);

System.out.println(date1.isBefore(date2));
System.out.println(date1.isAfter(date2));

This results in:

true
false

Using LocalDate.compareTo()

Extending Comparable, the LocalDate class has a compareTo() method, which returns an integer greater, less, or equal to zero. The fields are compared in order and the first field that is non-equal is used to determine the result:

LocalDate today = LocalDate.now();
LocalDate tomorrow = new LocalDate(today.getYear(),
                                   today.getMonthOfYear(), 
                                   today.getDayOfMonth() + 1);
int result = today.compareTo(tomorrow);

if(result == 0)
    System.out.println("Dates are equal");
else if (result < 0)
    System.out.println(today + " is before " + tomorrow);
else
    System.out.println(today + " is after " + tomorrow);
    

This results in:

2021-04-14 is before 2021-04-15

Using LocalDate.equals()

And finally, the equals() method checks for object reference equality:

LocalDate date1 = new LocalDate(2021, 3, 25);
LocalDate date2 = new LocalDate(2021, 2, 25);
System.out.println(date1.equals(date2));

This results in:

false

Conclusion

In this article, we've covered several ways to compare dates in Java. We've used the now-deprecated java.util.Date class, for older proejcts, and the java.util.Calendar class.

Then, we've jumped into the more modern Java 8 Date/Time API, and finally Joda-Time.

Last Updated: May 11th, 2021

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

Want a remote job?

    Prepping for an interview?

    • Improve your skills by solving one coding problem every day
    • Get the solutions the next morning via email
    • Practice on actual problems asked by top companies, like:
     
     
     

    Git Essentials

    Check out this hands-on, practical guide to learning Git, with best-practices and industry-accepted standards. Stop Googling Git commands and actually learn it!

    © 2013-2021 Stack Abuse. All rights reserved.