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 use java.time.Duration class?

java.time.Duration is another useful class in Java for dealing with time. It measures time in seconds and nanoseconds and is most suitable for smaller amounts of time, like “20 seconds” or “3 hours”, and not for larger units like “3 days” or “4 months”. Here’s a guide on how to use it:

1. Creating a Duration instance

You can create an instance of Duration using one of its static factory methods that best suits your needs, such as ofSeconds(), ofMinutes(), ofHours(), or ofMillis().

//create a duration of 60 seconds
Duration duration = Duration.ofSeconds(60);

//create a duration of 2 hours
Duration twoHours = Duration.ofHours(2);

2. Creating a Duration between two Instants

Duration also provides a static method between() that can be used to find the duration between two points in time.

Instant start = Instant.now();
// Do some time consuming task...
Instant end = Instant.now();

Duration duration = Duration.between(start, end);

3. Retrieving the Duration

You can retrieve the number of days, hours, minutes, or seconds in a Duration using methods like toDays(), toHours(), toMinutes(), or getSeconds().

long hours = twoHours.toHours();  // returns 2

4. Adding and Subtracting from a Duration

Duration can be added or subtracted from another using the plus() and minus() methods or the more specific plus / minus methods such as plusHours(), minusMinutes(), etc.

// Adding
Duration additionalDuration = duration.plusHours(4);

// Subtracting
Duration lessDuration = additionalDuration.minusMinutes(50);

5. Comparing Durations

The Duration class provides compareTo(), equals(), negated(), and abs() methods for comparison:

Duration duration1 = Duration.ofHours(4);
Duration duration2 = Duration.ofHours(2);

// Returns a negative number, zero, or positive number if less than, 
// equal to, or greater than the other.
int comparison = duration1.compareTo(duration2);

boolean equals = duration1.equals(duration2); // false

// Returns a duration with the new duration being negative of this 
// duration.
Duration negated = duration1.negated(); 

// Returns a duration with the new duration being absolute of 
// this duration, effectively, it returns the same as duration1.
Duration abs = negated.abs(); 

How do I use java.time.Period class?

java.time.Period is a class that represents a quantity or amount of time in terms of years, months, and days. Here’s a brief guide on how to use it:

1. Creating a Period instance

The Period class provides several static methods named of() and between() to create an instance. To create Period of 1 year, 2 months, and 3 days:

Period period = Period.of(1, 2, 3);

Or you can create a Period using LocalDate:

LocalDate start = LocalDate.of(2020, Month.JANUARY, 1);
LocalDate end = LocalDate.of(2023, Month.MARCH, 31);
Period period = Period.between(start, end);

2. Retrieving Years, Months, and Days

Use the getDays(), getMonths(), and getYears() methods to get the number of days, months, and years in the Period.

int days = period.getDays();
int months = period.getMonths();
int years = period.getYears();

3. Adding/subtracting Period to/from a LocalDate

The LocalDate.plus() or LocalDate.minus() methods can be used to add or subtract a Period from a LocalDate.

LocalDate ld = LocalDate.of(2021, Month.JULY, 1);
Period period = Period.of(1, 2, 3);
LocalDate newDate = ld.plus(period);

In this case, newDate will be 1 year, 2 months, and 3 days after July 1, 2021.

4. Mixing units of time

You can use plusDays(), plusMonths(), or plusYears() to add to a Period.

Period period = Period.of(1, 2, 3);
Period newPeriod = period.plusDays(10);

The newPeriod will then be 1 year, 2 months, and 13 days.

How do I use ChronoUnit enumeration?

ChronoUnit is an enumeration that provides static constants representing the units of time in the date-time API in Java. These constants include DAYS, HOURS, SECONDS, etc., that are often used to measure a quantity of time with respect to the specifics of a calendar system.

Here’s an example of how you can use the ChronoUnit enumeration:

package org.kodejava.datetime;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class ChronoUnitExample {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();

        LocalDateTime tenDaysLater = now.plus(10, ChronoUnit.DAYS);
        System.out.println("Date 10 days from now: " + tenDaysLater);

        LocalDateTime twoHoursLater = now.plus(2, ChronoUnit.HOURS);
        System.out.println("Time 2 hours from now: " + twoHoursLater);
    }
}

Output:

Date 10 days from now: 2024-01-27T21:24:22.397516900
Time 2 hours from now: 2024-01-17T23:24:22.397516900

In this sample, we use the plus method of LocalDateTime that takes two parameters: a long amount to add and a TemporalUnit. We pass to it a constant from ChronoUnit.

We can also measure the difference between two date-time objects, like so:

package org.kodejava.datetime;

import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class DateTimeDiff {
    public static void main(String[] args) {
        LocalTime start = LocalTime.of(14, 30);
        LocalTime end = LocalTime.of(16, 30);

        long elapsedMinutes = ChronoUnit.MINUTES.between(start, end);
        System.out.println("Elapsed minutes: " + elapsedMinutes);
    }
}

Output:

Elapsed minutes: 120

In the above example, the between method from ChronoUnit was used to calculate the difference in minutes between start and end times.

How do I use plus and minus method in the Java Date-Time API?

In the Java Date-Time API, the plus and minus methods can be used to calculate and modify dates, times, date/times, and durations.

Each temporal class (LocalDate, LocalTime, LocalDateTime, and Duration) includes these methods.

Here’s a basic example using the LocalDate class:

package org.kodejava.datetime;

import java.time.LocalDate;

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

        // Calculate the date 5 days into the future
        LocalDate futureDate = date.plusDays(5);
        System.out.println("Date five days in the future: " + futureDate);

        // Calculate the date 5 days in the past.
        LocalDate pastDate = date.minusDays(5);
        System.out.println("Date five days in the past: " + pastDate);
    }
}

Output:

Date five days in the future: 2024-01-22
Date five days in the past: 2024-01-12

You can also use plusWeeks, plusMonths, plusYears, minusWeeks, minusMonths, minusYears methods in a similar manner to add or subtract the respective time period.

Note: All the datetime manipulation methods return a new instance of the date/time object; they do not modify the original object because the classes are immutable.

The plus() and minus() methods in the Java Date-Time API offer finer control over date-time arithmetic by allowing you to add or subtract different types of date-time units such as days, months, or years.

The plus() method is used to add specific time units to a date or time, while the minus() method is used to subtract specific time units.

Here’s an example:

package org.kodejava.datetime;

import java.time.LocalDate;
import java.time.Period;

public class PlusMinusOtherExample {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();

        // 1 year, 2 months, and 3 days.
        Period periodToAdd = Period.of(1, 2, 3);
        LocalDate futureDate = today.plus(periodToAdd);
        System.out.println("Date after adding a period: " + futureDate);

        // 2 years, 4 months, and 6 days.
        Period periodToSubtract = Period.of(2, 4, 6);
        LocalDate pastDate = today.minus(periodToSubtract);
        System.out.println("Date after subtracting a period: " + pastDate);
    }
}

The Period class is part of the Java Date-Time API and is used to represent a quantity of time in terms of years, months, and days.

Remember, you can create a Period using the Period.of(int years, int months, int days) method, where years, months, and days are the specific units of time to be represented.

Here are examples using LocalTime and LocalDateTime:

package org.kodejava.datetime;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class PlusMinusTime {
    public static void main(String[] args) {
        // Creating a LocalTime object and adding/subtracting hours, minutes, seconds
        LocalTime time = LocalTime.now();

        LocalTime futureTime = time.plus(2, ChronoUnit.HOURS);
        System.out.println("Time after two hours: " + futureTime);

        LocalTime pastTime = time.minus(30, ChronoUnit.MINUTES);
        System.out.println("Time 30 minutes ago: " + pastTime);

        // Creating a LocalDateTime object and adding/subtracting days, months, years
        LocalDateTime dateTime = LocalDateTime.now();

        LocalDateTime futureDateTime = dateTime.plus(1, ChronoUnit.YEARS);
        System.out.println("Date and Time one year into the future: " + futureDateTime);

        LocalDateTime pastDateTime = dateTime.minus(2, ChronoUnit.MONTHS);
        System.out.println("Date and Time two months ago: " + pastDateTime);

        // You can also use plus or minus Days, Weeks, Months, Years directly
        LocalDateTime exactDateTimeFuture = dateTime.plusDays(1).plusWeeks(1).plusMonths(1).plusYears(1);
        System.out.println("Date and Time after one day, week, month, and year: " + exactDateTimeFuture);
    }
}

Note that when we are adding/subtracting units like hours, minutes, and seconds, we use java.time.temporal.ChronoUnit. When adding/subtracting days, weeks, months, and years, we use directly plusDays or minusDays and so on.