Comparing Dates in Java: A Tutorial

Navigate to:

You’d be hard-pressed to find an application that doesn’t have time manipulation at all. Date comparisons, specifically, are vital in domains such as scheduling, event managing, supply, and logistics, to name a few. This is true regardless of programming language, but in this post, we’ll treat you to a Java date comparison guide.

We’ll open the blog with a brief digression into the two available APIs for date and time in Java and why the new API was released with the launch of Java 8. Then, we’ll dive into the tutorial, where you’ll learn how to compare dates in Java.

Let’s get started.

A tale of two Date/Time APIs

In Java, you have two APIs—two sets of classes and methods—to perform time manipulation with. The old one consists of classes from the java.util package, such as Date and Calendar. The new API—Java Time API—provides an array of classes belonging to the java.time package to handle time more comprehensively and robustly.

Why did the Java creators introduce the new API? In short, the old one had numerous problems, including:

  • Classes that were mutable and thus, not thread-safe.
  • Inadequate design that lacked types for handling common concepts necessary when handling time.
  • A lack of support for time-zone handling logic.

As we mentioned, the Java Time API was introduced with the release of Java 8 and has since been the recommended approach for handling time in Java. In this tutorial, we’ll use the new API for most examples. As of this writing, I have Java 21 installed on my machine, the latest LTS (long-time support) version.

We’ll talk briefly about the java.util.Date and java.util.Calendar classes for comprehensiveness’ sake, but they should not be used for new development.

Without further ado, let’s dig in.

How can I compare two dates in Java?

One interesting aspect of the Java Time API is that it provides many different types, each representing a different aspect of dates and times. So, we’ll teach you Java date comparison one type at a time.

Java LocalDate class

The LocalData class represents a date without the time component. The “local” suffix means it’s local concerning the context where it was created. It has no information about time zones, for instance.

Let’s see how to create two instances and compare them:

var a = LocalDate.of(2024, 2, 5);

var b = LocalDate.of(2024, 2, 6);

System.out.println(a.isEqual(b) ? "Same" : "Different");

if (a.isBefore(b)) {

` System.out.println(“‘a’ comes before ‘b’”);`

}

To explain the code above:

  • First, we instantiate two LocalDate objects, setting them to February 5th and February 6th of 2024, respectively.
  • Then, we use the isEqual() method to compare them for equality, resulting in “Different” being displayed.
  • Finally, we use the isBefore() method to verify whether one of the dates comes before the other.

Unsurprisingly, there’s also an isAfter() method we could’ve used.

Java LocalTime class

The LocalTime class is similar to the LocalDate one; it represents only the local time without the date component. Similar to its date counterpart, it has no awareness of time zones.

Let’s see how to instantiate this class.

var t1 = LocalTime.of(8, 0, 0);

var t2 = LocalTime.of(8, 0, 1);

What about the comparisons? The same methods are available (isEqual(), isBefore(), and isAfter()).

Java LocalDateTime class

The LocalDateTime class stores both the day and time data. Let’s see how you can get a shiny new LocalDateTime object:

var now = LocalDateTime.now();

var tomorrow = now.plusDays(1);

var date = LocalDateTime.of(2024, 2, 5, 8, 0, 1);

var date2 = LocalDateTime.of(2024, 2, 5, 8, 0, 1);

And for the comparisons? The same set of methods apply here as well.

Java Duration class

The Duration class represents a duration of time, such as 5 minutes, 10 hours, etc. Here is some code instantiating two objects:

Duration sixtyMinutes = Duration.ofMinutes(60);

Duration oneHour = Duration.ofHours(1);

This time I kept the C# programmer in me at bay and refrained from using type inference. As you can see, we create an object using the ofMinutes() static factory method and another one using the ofHours() method. Both objects are equivalent, and we should be able to compare them to prove that. Unlike the previous classes, the Duration class doesn’t have an isEqual() method.

So, we have to resort to the default equals() method:

if (oneHour.equals(sixtyMinutes)) {

` System.out.println(“Equals”);`

} else {

` System.out.println(“Different”);`

}

Awesome, but what if you compare two durations to determine which is longer? This is where the compareTo() method comes in handy. The method returns 0 if the values are equal, 1 if the value on which you’re calling the method is longer, and -1 if the value passed as a parameter is longer. Would you like an example?

Duration someDuration = Duration.ofMinutes(60);

Duration anotherDuration = Duration.ofMinutes(70);

var result = someDuration.compareTo(anotherDuration);

switch (result)

{

` case 0:`

` System.out.println(“They’re equal.”);`

` break;`

` case 1:`

` System.out.println(“First duration is longer.”);`

` break;`

` case -1:`

` System.out.println(“Second duration is longer.”);`

` break;`

}

Run the code above, and you’ll see that it displays “Second duration is longer.”

Java Period class

The Period class, similar to the Duration class, represents a time interval. But what’s the difference between them? In short, the Period class represents calendar-based time intervals such as “two months,” “one year,” and so on.

An example will help clarify. In the following code, I will:

  • Instantiate a LocalDate object
  • Create a Period object representing one month
  • Add the Period object to the LocalDate and verify the result

LocalDate januaryFirst = LocalDate.of(2024, 1, 1);

Period oneMonth = Period.ofMonths(1);

LocalDate janFirstPlusOneMonth = januaryFirst.plus(oneMonth);

System.out.println(janFirstPlusOneMonth); // displays "2024-02-01"

I think you’d agree that the result above is far from surprising. Now let’s tweak the example, making the start date February 1st.

LocalDate febFirst = LocalDate.of(2024, 2, 1);

Period oneMonth = Period.ofMonths(

LocalDate febFirstPlusOneMonth = febFirst.plus(oneMonth);

System.out.println(febFirstPlusOneMonth); // displays "2024-03-01"

Maybe you are surprised by the results above, maybe you aren’t. Maybe it isn’t clear what I’m getting at, so I’ll spell it out. From January 1st to February 1st, we have 31 days. From February 1st to March 1st, we have 29 days—of course, it’s usually 28, but 2024 is a leap year.

What’s happening is that the Period object we created above doesn’t care whether a month has 28, 29, 30, or 31 days. It just represents the human-centric, calendar-based concept of what a month is. The plus() method from LocalDate is smart enough to determine how many days it should effectively add when generating the new value.

After all the caveats above, how do you go about comparing periods? Nothing too surprising: the equals() and compareTo() methods are available and work just as expected.

Period p1 = Period.ofMonths(1);

Period p2 = Period.parse("P1M");

if (p1.equals(p2)) {

` System.out.println(“Of course they’re equal”);`

}

For the second value in the example above, I’ve created the instance using a different approach: I’ve parsed the textual representation of a period, according to the format standardized by ISO-8601. I did it just to add some variety, but the result is the same.

The old days: the Date and Calendar classes

As you’ve learned in this post, Java 8 introduced a revamped date and time API. It’s been a decade since then, and I recommend using the new classes for all your time-handling needs.

Nevertheless, you may still stumble upon legacy code lingering in the old API ways, so familiarizing yourself with the java.util classes might come in handy.

Let’s see an example comparing two dates:

Calendar feb10Calendar = new GregorianCalendar(2024, Calendar.FEBRUARY, 10);

Calendar feb15Calendar = new GregorianCalendar(2024, Calendar.FEBRUARY, 15);

Date date1 = feb10Calendar.getTime();

Date date2 = feb15Calendar.getTime();

if (date1.equals(date2)) {

` System.out.println(“They’re the same”);`

} else {

` System.out.println(“They’re NOT the same”);`

}

var comp = date1.compareTo(date2);

switch (comp)

{

` case 0:`

` System.out.println(“They’re the same”);`

` break;`

` case 1:`

` System.out.println(“First date comes after second date”);`

` break;`

` case -1:`

` System.out.println(“Second date comes after first date”);`

` break;`

}

The code above needs no explanation since the comparisons look identical to some previous examples, with the exception that creating the dates themselves requires more ceremony.

Java date comparison: do it the right way

Handling time is an everyday task in programming, but it’s harder than many developers give it credit for. This is true in all programming languages: Python, C#, Java—they’re all complicated.

In this post, we’ve explored one specific aspect of time handling: Java date comparisons. Java 8 brought a rich new time API, offering plenty of classes representing different aspects of date and time. As you’ve seen, comparing dates using the Java Time API is a breeze. If you are working with time-stamped data as a key part of your application, it may be worth checking out InfluxDB and the Java client library, which makes it easy to store and query your data in Java.

This post was written by Carlos Schults. Carlos is a skilled software engineer and an accomplished technical writer for various clients. His passion is to get to the bottom (the original source) of things and captivate readers with approachable and informative technical content.