Scala 3 dates: How to calculate the difference between two dates (LocalDate, ChronoUnit)

This is an excerpt from the Scala Cookbook, 2nd Edition. This is Recipe 3.10, Calculating The Difference Between Two Dates.

Problem

While using Scala (2 or 3), you need to determine the difference between two dates.

Solution

If you need to determine the number of days between two dates, the DAYS enum constant of the java.time.temporal.ChronoUnit class is the easiest solution:

import java.time.LocalDate
import java.time.temporal.ChronoUnit.DAYS

val now  = LocalDate.of(2019,  1, 20)   // 2019-01-20
val xmas = LocalDate.of(2019, 12, 25)   // 2019-12-25

DAYS.between(now, xmas)                 // Long = 339

If you need the number of years or months between two dates, you can also use the YEARS and MONTHS enum constants of ChronoUnit:

import java.time.LocalDate
import java.time.temporal.ChronoUnit._

val now = LocalDate.of(2019,  1, 20)              // 2019-01-20
val nextXmas = LocalDate.of(2020, 12, 25)         // 2020-12-25

val years: Long  = YEARS.between(now, nextXmas)   // 1
val months: Long = MONTHS.between(now, nextXmas)  // 23
val days: Long   = DAYS.between(now, nextXmas)    // 705

Using the same LocalDate values, you can also use the Period class, but notice the significant difference in the output between the ChronoUnit and Period approaches:

import java.time.Period

val diff = Period.between(now, nextXmas)   // P1Y11M5D
diff.getYears                              // 1
diff.getMonths                             // 11
diff.getDays                               // 5

Discussion

The between method of the ChronoUnit class takes two Temporal arguments:

between(temporal1Inclusive: Temporal, temporal2Exclusive: Temporal)

Therefore it works with all Temporal subclasses, including Instant, LocalDate, LocalDateTime, LocalTime, ZonedDateTime, and more. Here’s a LocalDateTime example:

import java.time.LocalDateTime
import java.time.temporal.ChronoUnit

// of(year, month, dayOfMonth, hour, minute)
val d1 = LocalDateTime.of(2020, 1, 1, 1, 1)
val d2 = LocalDateTime.of(2063, 4, 5, 1, 1)

ChronoUnit.DAYS.between(d1, d2)      // Long = 15800
ChronoUnit.YEARS.between(d1, d2)     // Long = 43
ChronoUnit.MINUTES.between(d1, d2)   // Long = 22752000

The ChronoUnit class has many other enum constants including CENTURIES, DECADES, HOURS, MICROS, MILLIS, SECONDS, WEEKS, YEARS, and more.

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller