java-date-difference
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
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
2. Core 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(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
<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.