ChronoUnit and TemporalAdjusters
ChronoUnit and TemporalAdjusters are two helpers in the java.time.temporal package. ChronoUnit is an enum of time units, from NANOS to MILLENNIA. It is used to count the amount of time between two dates or times in one unit, and to add or truncate by a unit. TemporalAdjusters is a class of ready-made rules that move a date to a related date, such as "the last day of this month" or "the next Monday". In this lesson, you will learn both with examples.
ChronoUnit
| Use | Example |
|---|---|
| Count between two values | ChronoUnit.DAYS.between(start, end) |
| Add or subtract by a unit | date.plus(2, ChronoUnit.WEEKS) |
| Cut off smaller units | time.truncatedTo(ChronoUnit.MINUTES) |
Common units: NANOS, MILLIS, SECONDS, MINUTES, HOURS, HALF_DAYS, DAYS, WEEKS, MONTHS, YEARS, DECADES, CENTURIES.
Example: Counting and Adding with ChronoUnit
Let's see an example that counts the time until an exam.
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class Units {
public static void main(String[] args) {
LocalDate today = LocalDate.of(2026, 11, 12);
LocalDate exam = LocalDate.of(2027, 3, 1);
System.out.println("Days to exam: "
+ ChronoUnit.DAYS.between(today, exam));
System.out.println("Weeks to exam: "
+ ChronoUnit.WEEKS.between(today, exam));
System.out.println("Months to exam: "
+ ChronoUnit.MONTHS.between(today, exam));
System.out.println("Two weeks later: "
+ today.plus(2, ChronoUnit.WEEKS));
LocalDateTime stamp = LocalDateTime.of(2026, 11, 12, 14, 47, 31);
System.out.println("Truncated to hour: "
+ stamp.truncatedTo(ChronoUnit.HOURS));
}
}Days to exam: 109
Weeks to exam: 15
Months to exam: 3
Two weeks later: 2026-11-26
Truncated to hour: 2026-11-12T14:00Explanation: ChronoUnit.X.between counts whole units, so 109 days is 15 whole weeks and 3 whole months (not 4, because 1 March is before 12 March). plus(2, WEEKS) adds 14 days. truncatedTo(HOURS) drops the minutes and seconds.
TemporalAdjusters
| Method | Description |
|---|---|
firstDayOfMonth() / lastDayOfMonth() | It is used to move to the first or last day of the month. |
firstDayOfNextMonth() | It moves to the 1st of the next month. |
firstDayOfYear() / lastDayOfYear() | It moves to 1 January or 31 December. |
next(DayOfWeek) / previous(DayOfWeek) | It moves to the next or previous given weekday, never today. |
nextOrSame(DayOfWeek) / previousOrSame(DayOfWeek) | The same, but today counts if it matches. |
firstInMonth(DayOfWeek) / lastInMonth(DayOfWeek) | It moves to the first or last given weekday of the month. |
dayOfWeekInMonth(n, DayOfWeek) | It moves to the n-th given weekday of the month. |
Adjusters are applied with date.with(adjuster).
Example: Jumping to Related Dates
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class Adjusters {
public static void main(String[] args) {
LocalDate today = LocalDate.of(2026, 11, 12);
System.out.println("Today: " + today + " "
+ today.getDayOfWeek());
System.out.println("Last of month: "
+ today.with(TemporalAdjusters.lastDayOfMonth()));
System.out.println("Next Monday: "
+ today.with(TemporalAdjusters.next(DayOfWeek.MONDAY)));
System.out.println("Next Thursday: "
+ today.with(TemporalAdjusters.next(DayOfWeek.THURSDAY)));
System.out.println("This or next Thu: "
+ today.with(TemporalAdjusters.nextOrSame(DayOfWeek.THURSDAY)));
System.out.println("Second Saturday: "
+ today.with(
TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.SATURDAY)));
System.out.println("Last Friday: "
+ today.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)));
}
}Today: 2026-11-12 THURSDAY
Last of month: 2026-11-30
Next Monday: 2026-11-16
Next Thursday: 2026-11-19
This or next Thu: 2026-11-12
Second Saturday: 2026-11-14
Last Friday: 2026-11-27Explanation: Each adjuster moves the date by a rule. Today is a Thursday, so next(THURSDAY) skips to the following week, while nextOrSame(THURSDAY) returns today. dayOfWeekInMonth(2, SATURDAY) finds the second Saturday of November.
Common Mistakes
Expecting MONTHS.between to round up. It counts whole months only.
Using next(day) when today should count. Use nextOrSame.
Calling date.with(...) and ignoring the result. Dates are immutable; save the returned value.
Practice
- Easy: Print the first Monday and the last Sunday of every month in 2027.
- Harder: Write a
TemporalAdjusterlambdanextWorkingDaythat skips Saturdays and Sundays, and test it on a Friday and a Saturday.
Key Takeaways
Was this tutorial helpful?