Difference Between Two Dates in Java

1. Overview

In this quick write-up, we’ll explore multiple possibilities of calculating the difference between two dates in Java.

Further reading:

Increment Date in Java

An overview of various core and 3rd party methods for adding days to a date

Read more

Check If a String Is a Valid Date in Java

Have a look at different ways to check if a String is a valid date in Java

Read more

2. Core Java


==== 2.1. Using java.util.Date to Find the Difference in Days

Let’s start by using the core Java APIs to do the calculation and determine the number of days between the two dates:

@Test
public void givenTwoDatesBeforeJava8_whenDifferentiating_thenWeGetSix()
  throws ParseException {

    SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
    Date firstDate = sdf.parse("06/24/2017");
    Date secondDate = sdf.parse("06/30/2017");

    long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime());
    long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);

    assertEquals(diff, 6);
}

2.2. Using java.time – Since Java 8

Now, calculating the difference is more intuitive if we use LocalDate, LocalDateTime to represent the two dates (with or without time) in combination with Period and Duration:

The LocalDate difference:

@Test
public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
    LocalDate now = LocalDate.now();
    LocalDate sixDaysBehind = now.minusDays(6);

    Period period = Period.between(now, sixDaysBehind);
    int diff = period.getDays();

    assertEquals(diff, 6);
}

The LocalDateTime case:

@Test
public void givenTwoDateTimesInJava8_whenDifferentiating_thenWeGetSix() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime sixMinutesBehind = now.minusMinutes(6);

    Duration duration = Duration.between(now, sixMinutesBehind);
    long diff = Math.abs(duration.toMinutes());

    assertEquals(diff, 6);
}

Here‘s a bit more detail on this API.

2.3. Using java.time.temporal.ChronoUnit to Find the Difference in Seconds

The Time API in Java 8 represents a unit of date-time, e.g. seconds or days, using TemporalUnit interface. Each unit provides an implementation for a method named between to calculate the amount of time between two temporal objects in terms of that specific unit.

For example, in order to calculate the seconds between two LocalDateTimes:

@Test
public void givenTwoDateTimesInJava8_whenDifferentiatingInSeconds_thenWeGetTen() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime tenSecondsLater = now.plusSeconds(10);

    long diff = ChronoUnit.SECONDS.between(now, tenSecondsLater);

    assertEquals(diff, 10);
}

ChronoUnit provides a set of concrete time units by implementing the TemporalUnit interface. It’s highly recommended to static import the ChronoUnit enum values to achieve more readability:

import static java.time.temporal.ChronoUnit.SECONDS;

// omitted
long diff = SECONDS.between(now, tenSecondsLater);

Also, we can pass any two compatible temporal objects to the between method, even the ZonedDateTime.

What’s great about ZonedDateTime is that the calculation will work even if they are set to different timezones:

@Test
public void givenTwoZonedDateTimesInJava8_whenDifferentiating_thenWeGetSix() {
    LocalDateTime ldt = LocalDateTime.now();
    ZonedDateTime now = ldt.atZone(ZoneId.of("America/Montreal"));
    ZonedDateTime sixMinutesBehind = now
      .withZoneSameInstant(ZoneId.of("Asia/Singapore"))
      .minusMinutes(6);

    long diff = ChronoUnit.MINUTES.between(sixMinutesBehind, now);

    assertEquals(diff, 6);
}

2.4. Using java.time.temporal.Temporal until()

Any Temporal object, e.g. LocalDate or ZonedDateTime, provides an until method to calculate the amount of time until another temporal in terms of the specified unit:

@Test
public void givenTwoDateTimesInJava8_whenDifferentiatingInSecondsUsingUntil_thenWeGetTen() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime tenSecondsLater = now.plusSeconds(10);

    long diff = now.until(tenSecondsLater, ChronoUnit.SECONDS);

    assertEquals(diff, 10);
}

The Temporal#until and TemporalUnit#between are two different APIs for the same functionality.

3. External Libraries


==== 3.1. JodaTime

We can also do a relatively straightforward implementation with JodaTime:

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.9</version>
</dependency>

You can get the latest version of Joda-time from Maven Central.

LocalDate case:

@Test
public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() {
    LocalDate now = LocalDate.now();
    LocalDate sixDaysBehind = now.minusDays(6);

    Period period = new Period(now, sixDaysBehind);
    long diff = Math.abs(period.getDays());

    assertEquals(diff, 6);
}

Similarly, with LocalDateTime it is:

@Test
public void givenTwoDateTimesInJodaTime_whenDifferentiating_thenWeGetSix() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime sixMinutesBehind = now.minusMinutes(6);

    Period period = new Period(now, sixMinutesBehind);
    long diff = Math.abs(period.getDays());
}

3.2. Date4J

Date4j also provides a straightforward and simple implementation, without the note that, in this case, we need to explicitly provide a TimeZone.

Let’s start with the Maven dependency:

<dependency>
    <groupId>com.darwinsys</groupId>
    <artifactId>hirondelle-date4j</artifactId>
    <version>1.5.1</version>
</dependency>

Here’s a quick test working with the standard DateTime:

@Test
public void givenTwoDatesInDate4j_whenDifferentiating_thenWeGetSix() {
    DateTime now = DateTime.now(TimeZone.getDefault());
    DateTime sixDaysBehind = now.minusDays(6);

    long diff = Math.abs(now.numDaysFrom(sixDaysBehind));

    assertEquals(diff, 6);
}

4. Conclusion

In this tutorial, we illustrated a few ways of calculating the difference between dates (with and without time), both in plain Java as well as using external libraries.

The full source code of the article is available over on GitHub.

Leave a Reply

Your email address will not be published.