Date & Time API

Durations & Periods

15 min Lesson 4 of 13

Durations & Periods

The previous lesson introduced LocalDate, LocalTime, and LocalDateTime as points on the timeline. This lesson is about amounts of time — the gap between two points, or a quantity of time you want to add or subtract. Java's java.time API provides two distinct classes for this, each modelling a different concept:

  • Duration — a time-based amount measured in seconds and nanoseconds. Use it with LocalTime, LocalDateTime, Instant, or any class that includes a time component.
  • Period — a date-based amount measured in years, months, and days. Use it with LocalDate or the date portion of a LocalDateTime.
Why two separate classes? Because "30 days" and "1 month" are not the same thing. A month can have 28, 29, 30, or 31 days depending on the calendar. Period works in calendar units and handles that variation correctly, while Duration works in exact seconds and is calendar-agnostic. Confusing them leads to subtle bugs — the API forces you to choose consciously.

Duration

A Duration is always stored as a total number of seconds plus a nanosecond adjustment. Its factory methods let you express the amount in a human-readable unit:

import java.time.*; Duration twoHours = Duration.ofHours(2); Duration ninetyMins = Duration.ofMinutes(90); Duration halfSecond = Duration.ofMillis(500); Duration precise = Duration.ofSeconds(45, 250_000_000); // 45.25 s // Inspect the components System.out.println(twoHours.toHours()); // 2 System.out.println(twoHours.toMinutes()); // 120 System.out.println(twoHours.toSeconds()); // 7200 System.out.println(twoHours.toNanos()); // 7200000000000

The most powerful factory is Duration.between(), which computes the gap between two temporal objects of the same type:

LocalTime start = LocalTime.of(9, 30); LocalTime end = LocalTime.of(17, 15); Duration workday = Duration.between(start, end); System.out.println(workday.toHours()); // 7 System.out.println(workday.toMinutesPart()); // 45 (Java 9+) System.out.println(workday); // PT7H45M

toMinutesPart() (Java 9) returns the minutes component (0–59), not the total. This is the idiomatic way to format a duration without manual arithmetic.

Java 9 "part" methods: toHoursPart(), toMinutesPart(), toSecondsPart(), and toNanosPart() break a Duration into its human-readable components. Before Java 9 you had to do the arithmetic yourself (e.g. minutes % 60).

Duration Arithmetic

Duration is immutable. Every mutating method returns a new instance:

Duration d = Duration.ofMinutes(90); Duration longer = d.plusMinutes(30); // 120 min Duration shorter = d.minusSeconds(60); // 89 min Duration doubled = d.multipliedBy(2); // 180 min Duration halved = d.dividedBy(2); // 45 min boolean negative = d.isNegative(); // false Duration absolute = d.abs(); // useful when order of subtraction is unknown

Period

A Period stores years, months, and days as three separate integer fields — it does not convert between them. Adding a period of one month to 31 January gives 28 February (or 29 in a leap year), not 31 days later, because the calendar arithmetic is done correctly at the moment of application.

Period threeMonths = Period.ofMonths(3); Period oneYear = Period.ofYears(1); Period twoWeeks = Period.ofWeeks(2); // stored as 14 days Period complex = Period.of(1, 6, 15); // 1 year, 6 months, 15 days System.out.println(complex.getYears()); // 1 System.out.println(complex.getMonths()); // 6 System.out.println(complex.getDays()); // 15 System.out.println(complex); // P1Y6M15D

Period.between()

Like Duration.between(), Period.between() computes the difference between two LocalDate values in calendar units:

LocalDate birthdate = LocalDate.of(1995, 6, 15); LocalDate today = LocalDate.of(2026, 6, 9); Period age = Period.between(birthdate, today); System.out.printf("Age: %d years, %d months, %d days%n", age.getYears(), age.getMonths(), age.getDays()); // Age: 30 years, 11 months, 25 days
Do not use Duration.between() on LocalDate. LocalDate has no time component, so passing it to Duration.between() throws a UnsupportedTemporalTypeException. Always match the class: Duration for time-bearing objects, Period for date-only objects.

Period Arithmetic

Period p = Period.of(1, 2, 10); // 1 year, 2 months, 10 days Period more = p.plusMonths(3); // P1Y5M10D Period negated = p.negated(); // P-1Y-2M-10D boolean isNeg = p.isNegative(); // false (original) long totalMonths = p.toTotalMonths(); // 14 (years * 12 + months, days ignored)

Note that toTotalMonths() ignores the days field. There is no toTotalDays() because that would require calendar knowledge (a month is not a fixed number of days). If you need total days between two dates, use ChronoUnit.DAYS.between(start, end) instead.

ChronoUnit.between() — a Simpler Alternative

Sometimes you just want a single number: "how many full weeks between these two dates?" ChronoUnit makes this one-liner:

import java.time.temporal.ChronoUnit; LocalDate start = LocalDate.of(2026, 1, 1); LocalDate end = LocalDate.of(2026, 6, 9); long days = ChronoUnit.DAYS.between(start, end); // 159 long weeks = ChronoUnit.WEEKS.between(start, end); // 22 long months = ChronoUnit.MONTHS.between(start, end); // 5

This always returns a single long truncated to whole units. Use it when you need a scalar number rather than a structured Period or Duration.

Applying Amounts to Date-Time Objects

Both classes implement TemporalAmount, so you can pass them to plus() and minus() on any compatible temporal:

LocalDate deadline = LocalDate.of(2026, 6, 9); LocalDate extended = deadline.plus(Period.ofWeeks(2)); // 2026-06-23 LocalDate oneYearAgo = deadline.minus(Period.ofYears(1)); // 2025-06-09 LocalDateTime meeting = LocalDateTime.of(2026, 6, 9, 14, 0); LocalDateTime later = meeting.plus(Duration.ofMinutes(90)); // 15:30
Rule of thumb: if your variable is a LocalDate, use a Period. If it contains a time component (LocalTime, LocalDateTime, Instant), use a Duration. When you mix them up the compiler often lets it through — but the runtime throws an exception, so the discipline needs to come from you.

Summary

Duration models machine time — an exact number of seconds and nanoseconds, calendar-agnostic. Period models human time — years, months, and days that respect the irregularity of the calendar. Both are immutable value objects. Use between() to measure the gap, and plus() / minus() to apply them. When you only need a single numeric count, reach for ChronoUnit.