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 a 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()
Again, as usual, compareTo()
compares instances and returns -1
, 0
, or 1
depending on the values of the LocalDate
s. 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));
}
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
Since we've created two LocalDate
s 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 the LocalDate
class (Joda-Time class) which is thread-safe.
Using DateTimeComparator
The DateTimeComparator
class is specifically made to compare dates. It works with ReadableInstant
s, String
s, Date
s, Calendar
s and Long
s. So, we'll have to convert our Joda-Time LocalDate
s, to Date
s:
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 LocalDate
s:
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 projects, and the java.util.Calendar
class.
Then, we've jumped into the more modern Java 8 Date/Time API, and finally Joda-Time.