Complete Java TemporalAdjuster interface tutorial covering all methods with examples. Learn about date adjustments in Java.
Last modified: April 16, 2025
The java.time.temporal.TemporalAdjuster interface provides flexible date adjustments. It allows complex date manipulations beyond simple plus/minus operations. Implementations can find the next or previous day of week.
TemporalAdjuster is a functional interface with a single method. It works with all temporal types in the java.time package. Common adjustments are provided by the TemporalAdjusters utility class.
The interface defines one method adjustInto that takes a temporal object and returns an adjusted version. The TemporalAdjusters class provides many predefined adjusters. Custom adjusters can implement complex logic.
public interface TemporalAdjuster { Temporal adjustInto(Temporal temporal); }
public final class TemporalAdjusters { public static TemporalAdjuster firstDayOfMonth(); public static TemporalAdjuster lastDayOfMonth(); public static TemporalAdjuster firstDayOfNextMonth(); public static TemporalAdjuster firstDayOfYear(); public static TemporalAdjuster lastDayOfYear(); public static TemporalAdjuster firstDayOfNextYear(); public static TemporalAdjuster next(DayOfWeek dayOfWeek); public static TemporalAdjuster nextOrSame(DayOfWeek dayOfWeek); public static TemporalAdjuster previous(DayOfWeek dayOfWeek); public static TemporalAdjuster previousOrSame(DayOfWeek dayOfWeek); }
The code shows the interface and key methods from TemporalAdjusters. These provide common date adjustments like finding month boundaries or specific weekdays. The adjusters are thread-safe and immutable.
The TemporalAdjusters class provides many useful adjusters. These handle common cases like finding month boundaries or specific weekdays. They can be used with any temporal type that supports the adjustment.
Main.java
package com.zetcode;
import java.time.LocalDate; import java.time.Month; import java.time.temporal.TemporalAdjusters; import java.time.DayOfWeek;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, Month.APRIL, 15);
// First day of month
LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("First day of month: " + firstDay);
// Last day of month
LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("Last day of month: " + lastDay);
// Next Tuesday
LocalDate nextTuesday = date.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
System.out.println("Next Tuesday: " + nextTuesday);
// First day of next year
LocalDate firstNextYear = date.with(TemporalAdjusters.firstDayOfNextYear());
System.out.println("First day of next year: " + firstNextYear);
}
}
This example demonstrates several predefined adjusters. Each adjustment creates a new date object without modifying the original. The adjusters handle edge cases like month length variations automatically.
TemporalAdjusters provides methods to find specific weekdays relative to a date. These include next, previous, and same-day variants. They are useful for scheduling recurring events.
Main.java
package com.zetcode;
import java.time.LocalDate; import java.time.Month; import java.time.temporal.TemporalAdjusters; import java.time.DayOfWeek;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, Month.APRIL, 15); // Tuesday
// Next Friday
LocalDate nextFriday = date.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
System.out.println("Next Friday: " + nextFriday);
// Previous Monday
LocalDate prevMonday = date.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
System.out.println("Previous Monday: " + prevMonday);
// Next or same Wednesday
LocalDate nextOrSameWed = date.with(TemporalAdjusters.nextOrSame(DayOfWeek.WEDNESDAY));
System.out.println("Next or same Wednesday: " + nextOrSameWed);
// Previous or same Friday
LocalDate prevOrSameFri = date.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY));
System.out.println("Previous or same Friday: " + prevOrSameFri);
}
}
This example shows weekday-related adjusters. The “next” and “previous” methods exclude the current day if it matches. The “OrSame” variants include the current day when it matches the target weekday.
Custom adjusters can implement complex date logic. They are created by implementing the interface or using lambda expressions. This provides flexibility for business-specific date rules.
Main.java
package com.zetcode;
import java.time.LocalDate; import java.time.Month; import java.time.temporal.Temporal; import java.time.temporal.TemporalAdjuster;
public class Main {
static class NextPaydayAdjuster implements TemporalAdjuster {
@Override
public Temporal adjustInto(Temporal temporal) {
LocalDate date = LocalDate.from(temporal);
int day = date.getDayOfMonth();
if (day < 15) {
return date.withDayOfMonth(15);
} else {
return date.withDayOfMonth(date.lengthOfMonth());
}
}
}
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, Month.APRIL, 10);
TemporalAdjuster paydayAdjuster = new NextPaydayAdjuster();
// Using class implementation
LocalDate nextPayday = date.with(paydayAdjuster);
System.out.println("Next payday: " + nextPayday);
// Using lambda expression
TemporalAdjuster taxDayAdjuster = t -> {
LocalDate d = LocalDate.from(t);
return d.withMonth(4).withDayOfMonth(15);
};
LocalDate taxDay = date.with(taxDayAdjuster);
System.out.println("Tax day: " + taxDay);
}
}
This example shows two ways to create custom adjusters. The first uses a class implementing the interface. The second uses a lambda expression. Both approaches can implement any date calculation logic needed.
Adjusters can be combined to perform multiple operations in sequence. Each adjustment is applied to the result of the previous one. This allows building complex date calculations from simple steps.
Main.java
package com.zetcode;
import java.time.LocalDate; import java.time.Month; import java.time.temporal.TemporalAdjusters; import java.time.DayOfWeek;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, Month.APRIL, 15);
// First go to first of month, then find next Friday
LocalDate result = date.with(TemporalAdjusters.firstDayOfMonth())
.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
System.out.println("First Friday of month: " + result);
// First find next Monday, then go to end of that month
LocalDate result2 = date.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("Last day of month containing next Monday: " + result2);
// Custom combined adjuster
TemporalAdjuster combined = t -> {
Temporal temp = TemporalAdjusters.firstDayOfMonth().adjustInto(t);
return TemporalAdjusters.next(DayOfWeek.WEDNESDAY).adjustInto(temp);
};
LocalDate result3 = date.with(combined);
System.out.println("First Wednesday of month: " + result3);
}
}
This example demonstrates combining adjusters in different ways. The first two examples chain adjustments directly. The third creates a combined adjuster as a lambda. All approaches achieve the same goal of sequential adjustments.
While commonly used with dates, TemporalAdjusters work with time objects too. They can adjust LocalDateTime, ZonedDateTime, and other temporal types. The adjustment logic must be compatible with the temporal type.
Main.java
package com.zetcode;
import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZonedDateTime; import java.time.ZoneId; import java.time.temporal.TemporalAdjusters; import java.time.DayOfWeek;
public class Main {
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.of(2025, 4, 15, 10, 30);
// Adjust LocalDateTime
LocalDateTime nextMonday = dateTime.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
System.out.println("Next Monday at same time: " + nextMonday);
// Adjust ZonedDateTime
ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("America/New_York"));
ZonedDateTime lastDay = zoned.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("Last day of month in NY: " + lastDay);
// Custom time adjuster
TemporalAdjuster toNoon = t -> {
if (t.isSupported(ChronoField.HOUR_OF_DAY)) {
return t.with(ChronoField.HOUR_OF_DAY, 12)
.with(ChronoField.MINUTE_OF_HOUR, 0)
.with(ChronoField.SECOND_OF_MINUTE, 0);
}
return t;
};
LocalDateTime noon = dateTime.with(toNoon);
System.out.println("Adjusted to noon: " + noon);
}
}
This example shows adjusters working with different temporal types. The custom time adjuster demonstrates handling time fields specifically. Note the check for field support before attempting adjustment.
A common use case is adjusting dates to business days. This requires skipping weekends and potentially holidays. The example shows a basic business day adjuster implementation.
Main.java
package com.zetcode;
import java.time.LocalDate; import java.time.DayOfWeek; import java.time.temporal.Temporal; import java.time.temporal.TemporalAdjuster; import java.time.temporal.ChronoUnit;
public class Main {
static class BusinessDaysAdjuster implements TemporalAdjuster {
private final int days;
public BusinessDaysAdjuster(int days) {
this.days = days;
}
@Override
public Temporal adjustInto(Temporal temporal) {
LocalDate date = LocalDate.from(temporal);
int remaining = days;
int step = Integer.signum(remaining);
while (remaining != 0) {
date = date.plus(step, ChronoUnit.DAYS);
if (date.getDayOfWeek() != DayOfWeek.SATURDAY &&
date.getDayOfWeek() != DayOfWeek.SUNDAY) {
remaining -= step;
}
}
return temporal.with(date);
}
}
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 4, 15); // Tuesday
TemporalAdjuster add5BusinessDays = new BusinessDaysAdjuster(5);
TemporalAdjuster subtract3BusinessDays = new BusinessDaysAdjuster(-3);
LocalDate in5Days = date.with(add5BusinessDays);
System.out.println("5 business days later: " + in5Days);
LocalDate before3Days = date.with(subtract3BusinessDays);
System.out.println("3 business days before: " + before3Days);
}
}
This example implements a business day adjuster that skips weekends. The adjuster works for both forward and backward adjustments. More complex versions could incorporate holiday calendars for complete business date calculations.
Java TemporalAdjuster Documentation
In this article, we’ve covered the essential methods and features of the Java TemporalAdjuster interface. Understanding these concepts is crucial for complex date manipulations in modern Java applications.
My name is Jan Bodnar, and I am a dedicated programmer with many years of experience in the field. I began writing programming articles in 2007 and have since authored over 1,400 articles and eight e-books. With more than eight years of teaching experience, I am committed to sharing my knowledge and helping others master programming concepts.
List all Java tutorials.