How do I use TemporalAdjusters dayOfWeekInMonth() method?

dayOfWeekInMonth() is a handy method in java.time.temporal.TemporalAdjusters class that returns an adjuster which changes the date to the n-th day of week in the current month.

Here is an example of how you could use it:

package org.kodejava.datetime;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

public class DayOfWeekInMonthExample {
    public static void main(String[] args) {
        // Current date
        LocalDate date = LocalDate.now();

        // The 2nd Tuesday in the month of the date.
        LocalDate secondTuesday = date.with(
                TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY));

        System.out.println("Current Date: " + date);
        System.out.println("Second Tuesday: " + secondTuesday);
    }
}

Output:

Current Date: 2024-01-18
Second Tuesday: 2024-01-09

This code would display the date of the second Tuesday in the current month.

Here’s what’s going on in this case:

  • TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY) specifies that we want the second occurrence of DayOfWeek.TUESDAY in the current month.

  • date.with(TemporalAdjuster) modifies the LocalDate date based on the TemporalAdjuster that is passed in. The original date object is unchanged; a new LocalDate reflecting the adjusted date is returned.

This TemporalAdjusters method is very useful when you have conditional logic based on things like “if it’s the third Monday of the month, then…”

How do I use java.time.temporal.TemporalAdjusters class?

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());

How do I create a custom TemporalAdjuster?

In this example we are going to learn how to implement a custom TemporalAdjuster. We are going to create TemporalAdjuster to find the next working day from a specified date. We will use 5 working days, from Monday to Friday.

The custom temporal adjuster class should implement the TemporalAdjuster interface, which define a single method that we must implement, the adjustInto(Temporal) method.

package org.kodejava.datetime;

import java.time.DayOfWeek;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;

public class NextWorkingDayAdjuster implements TemporalAdjuster {
    @Override
    public Temporal adjustInto(Temporal temporal) {
        int field = temporal.get(ChronoField.DAY_OF_WEEK);
        DayOfWeek dayOfWeek = DayOfWeek.of(field);

        int daysToAdd = 1;
        if (DayOfWeek.FRIDAY.equals(dayOfWeek)) {
            daysToAdd = 3;
        } else if (DayOfWeek.SATURDAY.equals(dayOfWeek)) {
            daysToAdd = 2;
        }
        return temporal.plus(daysToAdd, ChronoUnit.DAYS);
    }
}

The NextWorkingDayAdjuster move the temporal object a day forward. Except if it is on Friday or Saturday, which will move the temporal object three days or two days forward respectively. This will make it return Monday as the next working day.

After creating the custom adjuster, now let’s create an example that use the NextWorkingDayAdjuster class.

package org.kodejava.datetime;

import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalAdjuster;

public class NextWorkingDayAdjusterDemo {
    public static void main(String[] args) {
        TemporalAdjuster nextWorkingDay = new NextWorkingDayAdjuster();

        LocalDate now = LocalDate.now();
        LocalDate nextDay = now.with(nextWorkingDay);
        System.out.println("now            = " + now);
        System.out.println("nextWorkingDay = " + nextDay);

        LocalDate friday = LocalDate.of(2021, Month.MARCH, 11);
        nextDay = friday.with(nextWorkingDay);
        System.out.println("friday         = " + friday);
        System.out.println("nextWorkingDay = " + nextDay);

        LocalDate saturday = LocalDate.of(2021, Month.MARCH, 12);
        nextDay = saturday.with(nextWorkingDay);
        System.out.println("saturday       = " + saturday);
        System.out.println("nextWorkingDay = " + nextDay);
    }
}

And here are the results of our code:

now            = 2021-11-18
nextWorkingDay = 2021-11-19
friday         = 2021-03-11
nextWorkingDay = 2021-03-12
saturday       = 2021-03-12
nextWorkingDay = 2021-03-15

How do I manipulate LocalDate object using TemporalAdjuster?

In the previous example we manipulate the value of LocalDate by adding or subtracting the value of date object by days, months, years using methods like plusMonths() or minusDays(). Or by changing the year or the month of the date object using methods like withYear() or withMonth().

But there are times that we want to manipulate the date object so that we can get the first day of the month or the last day of the month. We want to manipulate the date value to advance the date to the first Monday after the current day or the last the of the year.

To manipulate the date object in this way we can use the with() method and pass a TemporalAdjuster object as an argument. Fortunately, the Date and Time API already provide some commonly used TemporalAdjuster. These TemporalAdjuster are provided as a static factory methods that we can find in the java.time.temporal.TemporalAdjusters class.

The following example is a code snippet to manipulate the date object using TemporalAdjuster / TemporalAdjusters class.

package org.kodejava.datetime;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

public class DateManipulationWithTemporalAdjuster {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now();
        System.out.println("Current date       = " + date);

        LocalDate date1 = date.with(TemporalAdjusters.firstDayOfMonth());
        System.out.println("First day of month = " + date1);

        LocalDate date2 = date.with(TemporalAdjusters.lastDayOfMonth());
        System.out.println("Last day of month  = " + date2);

        LocalDate date3 = date.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
        System.out.println("Next Monday        = " + date3);

        LocalDate date4 = date.with(TemporalAdjusters.lastDayOfYear());
        System.out.println("Last day of year   = " + date4);
    }
}

The result of the code snippet are:

Current date       = 2021-11-18
First day of month = 2021-11-01
Last day of month  = 2021-11-30
Next Monday        = 2021-11-22
Last day of year   = 2021-12-31

The table below shows the complete static factory methods provided by the TemporalAdjusters class.

Method Name Method Description
dayOfWeekInMonth Returns a new date in the same month with the ordinal day-of-week.
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 Returns a new date in the same month with the first matching day-of-week.
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 Returns a new date in the same month with the last matching day-of-week.
next Returns the next day-of-week adjuster.
nextOrSame Returns the next-or-same day-of-week adjuster.
ofDateAdjuster Returns user-written adjuster.
previous Returns the previous day-of-week adjuster.
previousOrSame Returns the previous-or-same day-of-week adjuster.

How do I get the date of the first particular day after a specific date?

In this example we will learn how to get the date of the first particular day that fall after a specific date. In the code snippet below we will find the first Friday that fall after the new year of 2021. First let’s create a LocalDate object that represent the new year of 2021. We can use LocalDate.of() factory method to create the date object.

To get the first occurrence of a specific day-of-week from a date we create a TemporalAdjuster using the TemporalAdjusters.next() method and pass the day-of-week, in this case we pass DayOfWeek.FRIDAY.

After that we create another LocalDate that will hold the next Friday date. The get the date for the next Friday we call newYear.with() method and pass the TemporalAdjuster that we have created earlier.

Now, let’s try the code snippet below.

package org.kodejava.datetime;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;

public class GetFirstDayAfterDate {
    public static void main(String[] args) {
        // Obtains the current date.
        LocalDate newYear = LocalDate.of(2021, Month.JANUARY, 1);
        System.out.println("New Year = " + newYear);

        // Gets the next Friday.
        TemporalAdjuster nextFriday = TemporalAdjusters.next(DayOfWeek.FRIDAY);
        LocalDate nextFridayDate = newYear.with(nextFriday);
        System.out.printf("The first Friday after the new year of %s is %s%n",
                newYear, nextFridayDate);
    }
}

The code snippet will print out the following result:

New Year = 2021-01-01
The first Friday after the new year of 2021-01-01 is 2021-01-08