In this post, we discuss the TemporalAdjuster in Java and some of the practical use cases for it.
Introduction
Java 8 introduced a new API for working with Date and Time.TemporalAdjuster is the part of this API which provides flexibility to perform complex operations on the data.To put it in simple terms, TemporalAdjuster is an implementation of the strategy design pattern using which the process of adjusting a value is externalized.
1. TemporalAdjuster
TemporalAdjuster is a functional interface with many predefined implementations in the TemporalAdjusters class.This interface contains only one method adjustInto() which execute by passing a temporal object to it.
@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}
TemporalAdjuster allows us to perform more complex data manipulation.To understand it more clearly let’s take an example of warehouse shipment.
- Shipment won’t happen over the weekend.
- We should show expected shipment date taking in to account weekends.
To handle these cases, TemporalAdjuster is the best candidate.
2. Predefined TemporalAdjusters
Java Date API provides set of predefined TemporalAdjuster as part of the TemporalAdjusters class.These predefined adjusters are to adjust date and time objects.Below is the list of adjusters provided by the TemporalAdjusters class.
dayIfWeekInMonth()
– day-of-week in month adjuster, which returns a new date in the same month with the ordinal day-of-week.firstDayOfMonth()
– Returns the “first day of month” adjuster, which returns a new date set to the first day of the current month.firstDayOfNextMonth()
– “first day of next month” adjuster, which returns a new date set to the first day of the next month.firstDayOfNextYear()
– Returns the “first day of next year” adjuster, which returns a new date set to the first day of the next year.firstDayOfYear()
– “first day of year” adjuster, which returns a new date set to the first day of the current year.
For the complete list of default adjusters, read TemporalAdjusters Javadcos.
2.1 TemporalAdjusters Example
Let’s work on an example to see how to use default methods provided byTemporalAdjusters class
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
public class TemporalAdjustersExample {
public static void main(String[] args) {
LocalDate localDateTime = LocalDate.now(); //taking current date time
System.out.println("First Day of the year:: "+localDateTime.with(TemporalAdjusters.firstDayOfYear()));
System.out.println("First Day of Month:: "+localDateTime.with(TemporalAdjusters.firstDayOfMonth()));
}
}
Output
First Day of the year:: 2018-01-01
First Day of Month:: 2018-03-01
3. Custom TemporalAdjuster
This class provides a number of adjusters, however, we may come into the situation, where these adjusters will not fulfill our requirements. To handle such situations, we should create custom adjuster by implementing TemporalAdjuster interface or using Java 8 Lambda expressions.Let’s create a custom adjuster for our warehouse functionality. We will adjust shipment date by skipping the weekend.
3.1 Custom Adjuster using Interface
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 OrderShipmentDateAdjuster implements TemporalAdjuster {
@Override
public Temporal adjustInto(Temporal temporal) {
DayOfWeek dayOfWeek = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
int nextShipmentDate = 1;
if(dayOfWeek == DayOfWeek.FRIDAY){
nextShipmentDate = 3;
}
else if(dayOfWeek==DayOfWeek.SATURDAY){
nextShipmentDate = 2;
}
return temporal.plus(nextShipmentDate, ChronoUnit.DAYS);
}
}
Let’s discuss what we did in this example.
- Next shipment date move by one day except for the weekends.
- If order placed on Friday, it’s shipped on Monday, we added 3 days to the next shipment date.
- For orders placed on Saturday, we added 2 days to the shipment date.
[pullquote align=”normal”]It is a recommendation to create custom adjusters for these use cases for easy use in your application. [/pullquote]
3.2 Custom Adjuster using Lambda Expression
Java 8 introduced lambda expressions. If you want to use lambda expressions for custom adjustor, use ofDateAdjuster
static factory method under TenporalAdjusters class.
TemporalAdjuster nextShipmentDay = TemporalAdjusters.ofDateAdjuster(temporal->{
DayOfWeek dayOfWeek = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
int nextShipmentDate = 1;
if(dayOfWeek == DayOfWeek.FRIDAY){
nextShipmentDate = 3;
}
else if(dayOfWeek==DayOfWeek.SATURDAY){
nextShipmentDate = 2;
}
return temporal.plus(nextShipmentDate, ChronoUnit.DAYS);
});
3.3 Use Custom Adjuster.
We created our first custom TemporalAdjuster in Java, let’s see how to use this adjuster in our code
public class TemporalAdjustersExample {
public static void main(String[] args) {
LocalDate localDate = LocalDate.now(); //taking current date time
LocalDate weekend = LocalDate.of(2018,03, 23);
OrderShipmentDateAdjuster shipmentDateAdjuster = new OrderShipmentDateAdjuster();
LocalDate date = localDate.with(shipmentDateAdjuster);
System.out.println(date);
LocalDate weekendDate = weekend.with(shipmentDateAdjuster);
System.out.println(weekendDate);
}
}
Using Lambda
public class TemporalAdjustersExample {
public static void main(String[] args) {
LocalDate localDate = LocalDate.now(); //taking current date time
LocalDate weekend = LocalDate.of(2018,03, 23);
TemporalAdjuster nextShipmentDay = TemporalAdjusters.ofDateAdjuster(temporal->{
DayOfWeek dayOfWeek = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
int nextShipmentDate = 1;
if(dayOfWeek == DayOfWeek.FRIDAY){
nextShipmentDate = 3;
}
else if(dayOfWeek==DayOfWeek.SATURDAY){
nextShipmentDate = 2;
}
return temporal.plus(nextShipmentDate, ChronoUnit.DAYS);
});
LocalDate date = localDate.with(nextShipmentDay);
System.out.println(date);
LocalDate weekendDate = weekend.with(nextShipmentDay);
System.out.println(weekendDate);
}
}
Output
2018-03-22
2018-03-26
Summary
In this post, we covered TemporalAdjuster in Java.We discussed different adjusters provided by TemporalAdjusters class. We covered the process of creating custom TemporalAdjuster with two different approaches and how to use these adjusters in our code.