The java.time.temporal.TemporalAdjuster
interface and the java.time.temporal.TemporalAdjusters
class are both part of the Java Date-Time API, and they work together for adjusting temporal objects.
TemporalAdjuster interface:
This is a functional interface, which means it has only one abstract method, adjustInto()
. This method is meant to adjust a temporal object, such as LocalDate
, LocalDateTime
, YearMonth
, etc. The single method makes it a suitable target for lambdas, which makes creating custom temporal adjusters a lot easier.
TemporalAdjusters class:
This class is effectively a factory/utility class that provides a number of pre-built implementations of TemporalAdjuster
that are commonly useful. These include adjusters to find the first/last day of the month, the next/previous day of the week, the next/previous occurrence of a specific day of the week and so on.
For example, if you wanted to find the next Friday, you would use TemporalAdjusters
to provide an implementation of TemporalAdjuster:
LocalDate nextFriday = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
In this code, TemporalAdjusters.next(DayOfWeek.FRIDAY)
is an instance of TemporalAdjuster
interface. The next()
static method in TemporalAdjusters
class provides the instance of TemporalAdjuster
.
Thus, while TemporalAdjuster
provides the mechanism to adjust temporal objects, TemporalAdjusters
provide a handy collection of frequently used implementations of this mechanism.
Let’s dive into how they’re commonly utilized:
1. Use predefined TemporalAdjusters
The TemporalAdjusters
class provides several static methods that return commonly used adjusters. For example, to get the next Sunday:
LocalDate localDate = LocalDate.now();
LocalDate nextSunday = localDate.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
Or the last day of the month:
LocalDate lastDayOfMonth = localDate.with(TemporalAdjusters.lastDayOfMonth());
2. Custom TemporalAdjuster
You can also create your own custom TemporalAdjuster
. For example, let’s suppose we want a TemporalAdjuster
that sets the time to 9 a.m.:
TemporalAdjuster adjuster = temporal -> {
return temporal.with(ChronoField.HOUR_OF_DAY, 9)
.with(ChronoField.MINUTE_OF_HOUR, 0)
.with(ChronoField.SECOND_OF_MINUTE, 0)
.with(ChronoField.NANO_OF_SECOND, 0);
};
LocalDateTime ldt = LocalDateTime.now();
ldt = ldt.with(adjuster);
In this case, ldt
is a new LocalDateTime
that shares the date with the original LocalDateTime
, but the time is set to 9 a.m.
3. Using TemporalAdjuster in date calculations
TemporalAdjuster
can also be used in more advanced date calculations such as finding the next weekday:
TemporalAdjuster NEXT_WORKDAY = TemporalAdjusters.ofDateAdjuster(
date -> {
DayOfWeek dow = date.getDayOfWeek();
int daysToAdd = 1;
if (dow == DayOfWeek.FRIDAY)
daysToAdd = 3;
else if (dow == DayOfWeek.SATURDAY)
daysToAdd = 2;
return date.plusDays(daysToAdd);
});
LocalDate nextWorkDay = localDate.with(NEXT_WORKDAY);
In this code block, NEXT_WORKDAY
is a TemporalAdjuster
that adjusts the date to the next workday. If the date falls on a Friday, it adds three days to skip the weekend. If it falls on a Saturday, it adds two days. In all other cases, it adds one day.
The java.time.temporal.TemporalAdjusters
class comes with many predefined TemporalAdjuster
implementations that are useful for common tasks. Here are some of them:
Temporal Adjuster |
Description |
dayOfWeekInMonth(int ord, DayOfWeek dow) |
Returns a new date in the same month with the ordinal day-of-week. The ordinal parameter allows you to specify which day of the week in the month, such as the “second Tuesday”. |
firstDayOfMonth() |
Returns a new date set to the first day of the current month. |
firstDayOfNextMonth() |
Returns a new date set to the first day of the next month. |
firstDayOfNextYear() |
Returns a new date set to the first day of the next year. |
firstDayOfYear() |
Returns a new date set to the first day of the current year. |
firstInMonth(DayOfWeek dow) |
Returns a new date in the same month with the first matching day-of-week. For example, “first Wednesday in March”. |
lastDayOfMonth() |
Returns a new date set to the last day of the current month. |
lastDayOfYear() |
Returns a new date set to the last day of the current year. |
lastInMonth(DayOfWeek dow) |
Returns a new date in the same month with the last matching day-of-week. For example, “last Wednesday in March”. |
next(DayOfWeek dow) or nextOrSame(DayOfWeek dow) |
Returns a new date that falls on the next specified day-of-week. If the current day is the specified day, this method returns a new date that is a week later. The nextOrSame() method will return today’s date if today is the specified day. |
previous(DayOfWeek dow) or previousOrSame(DayOfWeek dow) |
Behaves like next() or nextOrSame() , but returns a date that falls on the previous specified day-of-week. |
These methods can all be used with the with()
method of a date-based temporal object. For example:
// To get the last day of the current month:
LocalDate endOfMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());