How to calculate your next salary date using Java Temporal Adjuster?

Java 8 came up with a fresh set of packages for dealing with Time and Date.

Prior to this dealing with java dates was quite clumsy.

One such package is the java.time.temporal package which allows you to adjust a given date to another date based on certain rules like:

Given this date , what is the next Sunday or the next Friday or any day in a week?

Given this date , what is the previous Sunday or any day in a week?

Given this date , what is the first Monday of this month?

Given this date , what is the first day of next month or year? etc.

These are default TemporalAdjusters given by Java 8.

And we can create our own Temporal Adjusters too , like :

Given this date , what is my next salary date ?

Salary date usually falls on the last day of the month, but if it is a weekend it will be the previous Friday from the last date.

Let’s implement this.

First let’s find out the next Sunday from today.

I am writing this post on 24-May-2020 and the next Sunday from today is 31-May-2020.

Let’s check this using TemporalAdjusters.

Here is the client code:

                LocalDate today = LocalDate.now();

		LocalDate nextSunday = today.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));

		System.out.println("Date of next Sunday: " + nextSunday);

call with() method on the local date and pass a TemporalAdjusters instance to it.

The temporal adjusters instance I have used above is the one returned by the next() method of TemporalAdjusters API. It takes the day of the week as a parameter.

today.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));

And below is the output:

Date of next Sunday: 2020-05-31

That’s right!

Let’s create a custom Temporal Adjuster now.

This one as mentioned earlier , returns the next pay date.

To achieve this create a class which implements the interface TemporalAdjuster.

Here is the one I created:

package com.temporal.adjusters;

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

public class PayDayAdjuster implements TemporalAdjuster {

	@Override
	public Temporal adjustInto(Temporal inputDate) {
                //convert temporal date to LocalDate
		LocalDate date = LocalDate.from(inputDate);

                // get the last date of the current month
		LocalDate payDate = date.with(TemporalAdjusters.lastDayOfMonth());
                
                //check if it is a weekend
		boolean weekend = payDate.getDayOfWeek() == DayOfWeek.SATURDAY || payDate.getDayOfWeek() == DayOfWeek.SUNDAY;


                //if yes get the previous Friday
		if (weekend) {

			payDate = payDate.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
		}


		return payDate;
	}

}

The interface has a method adjustInto() which needs to be implemented by the custom class.

Here is the algorithm :

STEP 1: Convert the given temporal date to a Local Date instance

STEP 2: Get the last date of the current month

STEP 3: Check if it is a weekend

STEP 4: If it is a weekend , find out the previous Friday and return it , else return the last date of the month.

That’s it!

Now let’s find out the pay date using our custom Temporal Adjuster:

                LocalDate payDate = today.with(new PayDayAdjuster());

		System.out.println("Next pay date is on: " + payDate);

Just pass a new instance of PayDayAdjuster() to the with() method of local date.

Here is the output:

Next pay date is on:2020-05-29

Rightly so!

And , TemporalAdjusters is a functional interface. Any functional interface can be replaced with a lamda.

So we don’t have to create the class PayDayAdjuster in the above use case.

Instead we can pass the implementation inside the method adjustInto() directly as a parameter using lamda like this:

	LocalDate payDateLamda = today.with(t -> {

			LocalDate currDate = LocalDate.from(t);

			LocalDate salaryDate = currDate.with(TemporalAdjusters.lastDayOfMonth());

			if (salaryDate.getDayOfWeek() == DayOfWeek.SATURDAY || salaryDate.getDayOfWeek() == DayOfWeek.SUNDAY) {

				return salaryDate.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));

			}
			return salaryDate;
		});

System.out.println("Next pay date using lamda:" + payDateLamda);

Here is the output:

Next pay date using lamda:2020-05-29

The same output!

Here is the entire client code:

package com.temporal.adjusters;

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

public class Client {

	public static void main(String a[]) {

		LocalDate today = LocalDate.now();

		LocalDate nextSunday = today.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));

		System.out.println("Date of next Sunday: " + nextSunday);

		LocalDate payDate = today.with(new PayDayAdjuster());

		LocalDate payDateLamda = today.with(t -> {

			LocalDate currDate = LocalDate.from(t);

			LocalDate salaryDate = currDate.with(TemporalAdjusters.lastDayOfMonth());

			if (salaryDate.getDayOfWeek() == DayOfWeek.SATURDAY || salaryDate.getDayOfWeek() == DayOfWeek.SUNDAY) {

				return salaryDate.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));

			}
			return salaryDate;
		});

		System.out.println("Next pay date is on: " + payDate);

		System.out.println("Next pay date using lamda:" + payDateLamda);

	}
}

Date manipulation got cooler with Java 8.


Posted

in

by

Comments

Leave a Reply

Discover more from The Full Stack Developer

Subscribe now to keep reading and get access to the full archive.

Continue reading