Java Duration
Represent time-based amounts (hours, minutes, seconds) in Java with Duration.
Java Duration
Duration represents a length of time measured in seconds and nanoseconds. "Two hours." "Five hundred milliseconds." "Forty-five minutes." Internally it's two numbers — a long seconds and an int nanos — and every operation on it is integer arithmetic. It does not know about calendars, months, or DST; if you tell it 24 hours, it means exactly 86,400 seconds, regardless of whether that 24 hours happens to span a DST transition.
This is the right type for: timing measurements, timeouts, retries with exponential backoff, "wait at most X seconds," anything where the answer is a real-time interval. The companion type for calendar lengths ("one month," "two years") is Period, covered in the next chapter.
Creating
Three groups of factories:
Duration.ofNanos(500_000_000);
Duration.ofMillis(500);
Duration.ofSeconds(45);
Duration.ofSeconds(60, 500_000_000); // with nanos
Duration.ofMinutes(2);
Duration.ofHours(1);
Duration.ofDays(7); // exactly 7 * 24 hours
Duration.between(start, end); // from two Temporals
Duration.parse("PT1H30M"); // ISO-8601: PT[hours]H[minutes]M[seconds]SDuration.ofDays(n) is the factory most people use and most people misunderstand. It produces exactly n * 24 * 3600 seconds. On a DST transition day, that's not the same as "the next day at the same wall-clock time." For calendar-shaped "one day later," LocalDate.plusDays(1) or Period.ofDays(1) are the right tools.
The string format is ISO-8601 duration: PT1H30M45S is one hour, thirty minutes, forty-five seconds. The leading PT is mandatory (P = Period, T = Time). For sub-second components, the form is PT0.5S or PT0.000000001S. Duration covers everything below the day; periods (year, month, day) belong to Period.
Arithmetic
d.plus(Duration.ofSeconds(15));
d.plusSeconds(60);
d.plusMinutes(5);
d.plusHours(2);
d.minus(Duration.ofMillis(100));
d.multipliedBy(3);
d.dividedBy(2);
d.negated(); // -d
d.abs();Every method returns a new Duration (the immutability story from LocalDate onward).
The conversion accessors:
d.toNanos(); // long
d.toMillis(); // long; throws if out of long range
d.toSeconds(); // since Java 9
d.toMinutes();
d.toHours();
d.toDays(); // assumes 24h days
d.getSeconds(); // raw seconds component
d.getNano(); // raw nanos component (0-999_999_999)The toX() methods give you a single long of the total in that unit, truncating. The getX() methods give you the raw breakdown. They're different things; getting them confused is the most common Duration bug.
Duration d = Duration.ofSeconds(125);
d.toMinutes(); // 2 (125 / 60)
d.getSeconds(); // 125 (raw)For "X minutes Y seconds" formatting, use both:
long mins = d.toMinutes();
long secs = d.minusMinutes(mins).getSeconds();
System.out.printf("%d:%02d%n", mins, secs); // 2:05Or, since Java 9, the dedicated breakdown helpers:
d.toHoursPart(); // hours within the duration (0-23-ish on positive durations)
d.toMinutesPart(); // minutes within the duration (0-59)
d.toSecondsPart(); // seconds within the duration (0-59)
d.toMillisPart(); // millis within the secondThese are what you want for "render 1h 23m 45s" without doing the modulus yourself.
Comparing
d1.isZero(); // d == 0
d1.isNegative(); // d < 0
d1.compareTo(d2);
d1.equals(d2);Duration is Comparable<Duration>. The ordering is signed — a negative duration is less than zero is less than a positive duration.
Distance between two Temporals
The Duration.between(start, end) factory is the one you'll use most:
Duration d = Duration.between(start, end); // works on Instant, LocalDateTime, ZonedDateTime, LocalTimeIt accepts any pair of Temporal values that support time-based units. LocalDate (date only) does not — Duration.between(date1, date2) throws DateTimeException because a date has no clock component. For calendar distance, use Period.between(date1, date2) or ChronoUnit.DAYS.between(date1, date2).
The sign convention: positive if end is after start, negative otherwise.
Adding to other temporals
Duration is a TemporalAmount, so any Temporal accepts it via plus/minus:
Instant later = Instant.now().plus(Duration.ofMinutes(30));
LocalDateTime then = LocalDateTime.now().plus(Duration.ofHours(8));Adding a Duration to a LocalDate throws — same reason as above, no clock component. The compiler doesn't catch this; the call fails at runtime. If you find yourself wanting it, you almost certainly meant Period.
A worked example: timing, formatting, backoff
The program below measures the elapsed time of a small piece of work, prints it in a human-readable form using the toXxxPart helpers, computes an exponential-backoff schedule, and demonstrates the Duration vs Period boundary by showing both Duration.between on Instants and Period.between on LocalDates for the same conceptual time span.
What to take from the run:
- The
Thread.sleep(125)block measured asPT0.125-something-S— the actualsleepovershoot is real-machine variability.Duration.between(t0, t1)was the right call: twoInstants, no zone needed, exact answer to the resolution of the system clock. - The
toXxxPart()helpers gave clean integers for "the hours part," "the minutes part," "the seconds part," "the millis part." Without them you'd have to dototal / 3600and(total % 3600) / 60modular arithmetic by hand. Use them whenever you need to format a duration for a human. - The exponential-backoff loop scaled the duration with
multipliedBy(2)and printed each result. The ISO-8601 string form (PT2S,PT4S,PT8S, ...) is whatDuration.toStringprints; it's terse and unambiguous, ideal for logs. - The "Jan 1 → Apr 1 in three forms" block showed the
DurationvsPeriodboundary.Period.between(start, end)returnedP3M— three calendar months.Duration.betweenon the equivalent UTC instants returned a real-time count (90 days). Both are correct; they answer different questions. Pick the one whose meaning matches your code's intent. - The final block tried
Duration.between(LocalDate, LocalDate)and gotDateTimeException. The type system knows a date has no clock component, so it refuses to compute a clock-based duration. The fix is to either (1) attach times (startDate.atStartOfDay(zone)), or (2) usePeriod.betweenif a calendar count is what you actually meant. The exception is the right design: silent answers to that question would be misleading.
What's next
Duration is the seconds-and-nanos length. The next chapter, Java Period, is the years-months-days length — the calendar-shaped counterpart. The two never mix: Duration doesn't know about months, Period doesn't know about hours, and any code that fields both reaches for one or the other depending on whether the answer should track the calendar or the wall clock.
Practice
You want to retry an HTTP request after 'one day,' meaning '24 hours from now regardless of DST.' Which type and call do that?