**Get started with Spring 5 and Spring Boot 2, through the ***Learn Spring* course:

*Learn Spring*course:

**>> CHECK OUT THE COURSE**

Last modified: May 11, 2021

In this quick tutorial, we'll explore multiple possibilities of calculating the difference between two dates in Java.

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

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

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(6, diff);
}
```

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 *LocalDateTime*s:

```
@Test
public void givenTwoDateTimesInJava8_whenDifferentiatingInSeconds_thenWeGetTen() {
LocalDateTime now = LocalDateTime.now();
LocalDateTime tenSecondsLater = now.plusSeconds(10);
long diff = ChronoUnit.SECONDS.between(now, tenSecondsLater);
assertEquals(10, diff);
}
```

*ChronoUnit* provides a set of concrete time units by implementing the *TemporalUnit* interface. **It's highly recommended to static import the ChronoUnitenum values to achieve better 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 time zones:

```
@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(6, diff);
}
```

Any *Temporal* object, such as *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(10, diff);
}
```

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

In Java 8, the Time API introduced two new classes: *Duration *and *Period*.

**If we want to calculate the difference between two date-times in a time-based (hour, minutes, or seconds) amount of time, we can use the Duration class**:

```
@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(6, diff);
}
```

However, **we should be wary of a pitfall if we try using the Period class to represent the difference between two dates.**

An example will explain this pitfall quickly.

Let's calculate how many days between two dates using the *Period* class:

```
@Test
public void givenTwoDatesInJava8_whenUsingPeriodGetDays_thenWorks() {
LocalDate aDate = LocalDate.of(2020, 9, 11);
LocalDate sixDaysBehind = aDate.minusDays(6);
Period period = Period.between(aDate, sixDaysBehind);
int diff = Math.abs(period.getDays());
assertEquals(6, diff);
}
```

If we run the test above, it'll pass. We may think the *Period* class is convenient to solve our problem. So far, so good.

If this way works with a difference of six days, we don't doubt that it'll work for 60 days as well.

So let's change the *6* in the test above to *60* and see what happens:

```
@Test
public void givenTwoDatesInJava8_whenUsingPeriodGetDays_thenDoesNotWork() {
LocalDate aDate = LocalDate.of(2020, 9, 11);
LocalDate sixtyDaysBehind = aDate.minusDays(60);
Period period = Period.between(aDate, sixtyDaysBehind);
int diff = Math.abs(period.getDays());
assertEquals(60, diff);
}
```

Now if we run the test again, we'll see:

```
java.lang.AssertionError:
Expected :60
Actual :29
```

Oops! Why did the *Period* class report the difference as *29* days?

**This is because the Period class represents a date-based amount of time in the format of “x years, y months and z days”. **

Therefore, the *period *object in the test above holds the value “0 years, 1 month and 29 days”:

```
@Test
public void givenTwoDatesInJava8_whenUsingPeriod_thenWeGet0Year1Month29Days() {
LocalDate aDate = LocalDate.of(2020, 9, 11);
LocalDate sixtyDaysBehind = aDate.minusDays(60);
Period period = Period.between(aDate, sixtyDaysBehind);
int years = Math.abs(period.getYears());
int months = Math.abs(period.getMonths());
int days = Math.abs(period.getDays());
assertArrayEquals(new int[] { 0, 1, 29 }, new int[] { years, months, days });
}
```

**If we want to calculate the difference in days using Java 8's Time API, the ChronoUnit.DAYS.between() method is the most straightforward way.**

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() {
org.joda.time.LocalDate now = org.joda.time.LocalDate.now();
org.joda.time.LocalDate sixDaysBehind = now.minusDays(6);
long diff = Math.abs(Days.daysBetween(now, sixDaysBehind).getDays());
assertEquals(6, diff);
}
```

Similarly, with *LocalDateTime*:

```
@Test
public void givenTwoDateTimesInJodaTime_whenDifferentiating_thenWeGetSix() {
org.joda.time.LocalDateTime now = org.joda.time.LocalDateTime.now();
org.joda.time.LocalDateTime sixMinutesBehind = now.minusMinutes(6);
long diff = Math.abs(Minutes.minutesBetween(now, sixMinutesBehind).getMinutes());
assertEquals(6, diff);
}
```

*Date4j* also provides a straightforward and simple implementation — noting 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(6, diff);
}
```

In this article, 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.

1 Comment

Oldest