skip to content

What happens when you call Duration.between() on two LocalDate values, and what should you use instead?

level: middleimportance: should knowfreq 62%

answer

  1. Duration.between on LocalDate → UnsupportedTemporalTypeException: Unsupported unit: Seconds
  2. LocalDate has no time-of-day → no seconds to measure
  3. Period.between → years/months/days breakdown
  4. ChronoUnit.DAYS.between → single long count
  5. Duration.between needs time-carrying temporals (LocalDateTime/Instant/LocalTime)

basics

~10 s

It throws an exception (UnsupportedTemporalTypeException) because a LocalDate has no time-of-day, and Duration needs seconds. Use Period.between() for years/months/days, or ChronoUnit.DAYS.between() to get a number of days.

solid answer

~40 s

Duration.between expects temporals that support the SECONDS field; a LocalDate is a pure date with no time component, so calling Duration.between(date1, date2) throws UnsupportedTemporalTypeException: Unsupported unit: Seconds. To measure the gap between two dates, you have two correct options. Period.between(start, end) gives a calendar breakdown — years, months, and days — which is right for human-readable offsets. ChronoUnit.DAYS.between(start, end) (or WEEKS, MONTHS, YEARS) gives a single long count in that one unit, which is right when you want a plain number like 'how many days apart.' Duration.between only works when both arguments carry a time component, e.g. two LocalDateTime, Instant, or LocalTime values. A common fix when you actually have datetimes is to keep them as LocalDateTime/Instant rather than truncating to LocalDate.

code

java · 8 lines
java
LocalDate start = LocalDate.of(2026, 1, 15);
LocalDate end   = LocalDate.of(2026, 3, 20);

// Duration.between(start, end); // throws UnsupportedTemporalTypeException: Unsupported unit: Seconds

Period p = Period.between(start, end);          // P0Y2M5D (calendar breakdown)
long days = ChronoUnit.DAYS.between(start, end);// 64 (single total count)
long months = ChronoUnit.MONTHS.between(start, end); // 2 (whole months, truncated)

go deeper

for a junior

Knows Duration.between on dates fails and that Period.between or ChronoUnit.DAYS.between is the fix.

for a middle

Names the exact exception, explains it's because LocalDate lacks a time component, and chooses Period vs ChronoUnit by whether they want a breakdown or a single count.

for a senior

Explains it's an unchecked runtime exception (compiles fine), that ChronoUnit truncates, and recommends not truncating datetimes to dates when exact elapsed time is needed.

for a principal

Can reason about the supported-unit model underlying all temporal arithmetic, and guides API/domain design so callers can't accidentally pick the wrong amount type for the wrong temporal.

## Setup: what `between` needs The `java.time` API models points in time (`LocalDate`, `LocalTime`, `LocalDateTime`, `Instant`, …) as **temporals** that expose a set of supported **fields/units** (the things in `ChronoField`/`ChronoUnit`). Operations that compute an *amount* between two temporals require both temporals to support the unit that amount is expressed in. - A `LocalDate` (e.g. `2026-06-20`) supports date units: DAYS, MONTHS, YEARS… It has **no** hours, minutes, or seconds. - A `LocalTime`/`LocalDateTime`/`Instant` supports time units down to nanoseconds. ## Why `Duration.between(localDate, localDate)` throws `Duration` is measured in **seconds + nanoseconds**. `Duration.between(a, b)` internally asks the temporals for their SECONDS/NANOS. A `LocalDate` cannot answer that — it has no time-of-day — so the JVM throws: ``` java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds ``` This is a **runtime** exception (unchecked), not a compile error, which is why it surprises people: the code compiles fine because `LocalDate` is a `Temporal`, but it fails at execution. ## The two correct alternatives ### 1. `Period.between(startDate, endDate)` Returns a `Period` — a **calendar breakdown** into years, months, and days. Example: from `2026-01-15` to `2026-03-20` you get `P0Y2M5D` (0 years, 2 months, 5 days). Use this when you want a human-style "2 months and 5 days." Note `Period.between` is **not** symmetric in magnitude the way subtraction is — reversing the arguments gives a negative period, and the year/month/day split depends on the calendar between the two dates. ### 2. `ChronoUnit.<UNIT>.between(start, end)` Returns a single `long` in one chosen unit: ```java long days = ChronoUnit.DAYS.between(start, end); // total whole days long months = ChronoUnit.MONTHS.between(start, end); // total whole months long years = ChronoUnit.YEARS.between(start, end); ``` This is what you want for "how many days between two dates" — a flat number, truncated toward zero (whole units only; partial units are dropped). `ChronoUnit` works on any temporals that support the unit, so `ChronoUnit.DAYS.between(localDate1, localDate2)` is valid, whereas `Duration.between` is not. ## When `Duration.between` *is* correct When both arguments carry a time component: ```java Duration d = Duration.between( LocalDateTime.of(2026, 6, 20, 9, 0), LocalDateTime.of(2026, 6, 20, 17, 30)); // d = PT8H30M ``` or between two `Instant`s, or two `LocalTime`s. ## Practical guidance - Want a calendar offset (Y/M/D) → `Period.between`. - Want one number in a single unit (days, weeks, months) → `ChronoUnit.<UNIT>.between`. - Want exact elapsed time → make sure you have time-carrying temporals, then `Duration.between`. - If you 'lost' the time by truncating to `LocalDate`, the real fix is often to not truncate.

  • What does ChronoUnit.MONTHS.between return for 2026-01-31 to 2026-03-01?
    It returns 1 — only whole months are counted (Jan 31 → Feb 28/29 is not yet a full month into March; from Jan 31, one whole month reaches Feb 28, then the extra days to Mar 1 don't complete a second month), so partial units are truncated.
  • How would you get the precise hours between two LocalDate values at midnight?
    Convert each to a LocalDateTime via atStartOfDay() (ideally with a zone for DST correctness) and call Duration.between on the resulting datetimes, or use ChronoUnit.HOURS.between on the datetimes.

saying these in an interview costs you the question

  • Saying it returns 0 or null instead of throwing
  • Thinking it's a compile error (it's a runtime UnsupportedTemporalTypeException)
  • Using Period.between when you actually want a flat day count (Period splits into Y/M/D)
  • Assuming ChronoUnit.between rounds — it truncates to whole units

context