skip to content

What is ChronoUnit.between() and how does it differ from Period.between() and Duration.between()?

level: middleimportance: should knowfreq 55%

answer

  1. ChronoUnit = enum of units (DAYS, HOURS, MONTHS…) implementing TemporalUnit
  2. between() → single long, whole units only (truncates, signed)
  3. Period.between → Y/M/D object; Duration.between → secs/nanos object
  4. Period.getDays() = leftover days, ChronoUnit.DAYS.between = total days
  5. start.until(end, unit) == ChronoUnit.unit.between(start, end)

basics

~10 s

ChronoUnit.between(start, end) returns a single number (long) in one unit you choose, like DAYS or HOURS. Period.between returns a years/months/days object; Duration.between returns a seconds/nanos object.

solid answer

~40 s

ChronoUnit is an enum of time units (NANOS, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS, …). Each constant has a between(Temporal start, Temporal end) method that returns a single long counting how many whole units fit between the two temporals — e.g. ChronoUnit.DAYS.between(a, b) or ChronoUnit.HOURS.between(a, b). It truncates: partial units are dropped, and the result is negative if end precedes start. This differs from Period.between, which returns a structured Period broken into years+months+days, and Duration.between, which returns a Duration of seconds+nanoseconds. So ChronoUnit is the tool when you want one flat number in a specific unit; Period when you want a calendar breakdown; Duration when you want exact elapsed sub-day time. ChronoUnit.between only works when both temporals support the requested unit — DAYS works on LocalDate, but SECONDS does not.

go deeper

for a junior

Knows ChronoUnit.DAYS.between gives a number of days and that it's different from getting a Period.

for a middle

Explains ChronoUnit returns a single long in a chosen unit, truncates to whole units, is signed, and contrasts it with Period/Duration.between.

for a senior

Distinguishes Period.getDays() (leftover) from ChronoUnit.DAYS.between (total), knows the until() equivalence, and the unit-support exception.

for a principal

Reasons about choosing the right difference primitive for correctness and readability across a codebase, and the pitfalls of total-vs-leftover confusion in date math (e.g. age/tenure calculations).

## What `ChronoUnit` is `ChronoUnit` is an **enum** in `java.time.temporal` whose constants are the standard units of time: `NANOS`, `MICROS`, `MILLIS`, `SECONDS`, `MINUTES`, `HOURS`, `HALF_DAYS`, `DAYS`, `WEEKS`, `MONTHS`, `YEARS`, `DECADES`, `CENTURIES`, `MILLENNIA`, `ERAS`, `FOREVER`. Each implements the `TemporalUnit` interface. It plays two roles: 1. **A unit you pass to arithmetic:** `instant.plus(5, ChronoUnit.MINUTES)`, `Duration.of(2, ChronoUnit.HOURS)`. 2. **A difference calculator via `between`:** `ChronoUnit.DAYS.between(start, end)`. ## `ChronoUnit.<UNIT>.between(start, end)` This returns a single primitive `long`: the count of **complete** units of that type from `start` to `end`. ```java ChronoUnit.DAYS.between(LocalDate.of(2026,1,1), LocalDate.of(2026,1,11)); // 10 ChronoUnit.HOURS.between(t1, t2); // total whole hours ChronoUnit.MONTHS.between(d1, d2); // total whole months ``` Key behaviors: - **Truncation toward zero:** only whole units count; `ChronoUnit.DAYS.between(09:00 today, 08:00 tomorrow)` is `0` because a full day hasn't elapsed. Partial remainders are discarded, not rounded. - **Signed:** if `end` is before `start`, the result is negative. - **Unit support is required:** the unit must be supported by both temporals, or you get `UnsupportedTemporalTypeException`. `ChronoUnit.SECONDS.between(twoLocalDates)` throws for the same reason `Duration.between` does — a date has no seconds. `ChronoUnit.DAYS.between(twoLocalDates)` is fine. ## How it contrasts with the other two | Call | Returns | Shape | Best for | |---|---|---|---| | `ChronoUnit.X.between(a,b)` | `long` | one flat number in unit X | "how many days/hours/months apart?" | | `Period.between(a,b)` | `Period` | years + months + days (multi-field) | calendar breakdown, human display | | `Duration.between(a,b)` | `Duration` | seconds + nanos (one physical magnitude) | exact elapsed sub-day time | A subtle point people miss: `Period.between(d1, d2).getDays()` is **not** the same as `ChronoUnit.DAYS.between(d1, d2)`. The Period's `getDays()` is only the **leftover** days after whole years and months are pulled out (e.g. for a 64-day gap you might get `P2M5D`, so `getDays()` is `5`), whereas `ChronoUnit.DAYS.between` gives the **total** day count (`64`). ## Relationship to `until` `temporal.until(end, unit)` is the inverse view of the same operation: `start.until(end, ChronoUnit.DAYS)` equals `ChronoUnit.DAYS.between(start, end)`. (The single-arg `LocalDate.until(end)` instead returns a `Period`.) ## When to reach for it Reach for `ChronoUnit.between` whenever the answer you want is a single integer in one named unit. Reach for `Period`/`Duration` when you want a structured amount you'll add to another temporal or display as a multi-part breakdown.

  • What does ChronoUnit.DAYS.between(t1, t2) return if t2 is one hour before t1 on the same calendar day?
    0 — fewer than a full day separates them and the count truncates to zero whole days; if t2 is on a later date but less than 24h ahead in datetime terms it could still be 0 because between counts complete 24h spans for time-carrying temporals.
  • How can ChronoUnit help build a Duration?
    Use Duration.of(amount, ChronoUnit.X) — e.g. Duration.of(90, ChronoUnit.MINUTES) — since ChronoUnit constants are TemporalUnits accepted by Duration.of and by Temporal.plus.

saying these in an interview costs you the question

  • Confusing Period.getDays() with ChronoUnit.DAYS.between (leftover vs total)
  • Thinking ChronoUnit.between rounds rather than truncates
  • Assuming any unit works on any temporal (SECONDS on LocalDate throws)
  • Believing ChronoUnit.between returns an object — it returns a primitive long

context