Learn to find all business days between two given dates in Java. The business days are considered all weekdays, excluding all holidays falling on weekdays. Once we have a List of business dates, we can use the list.size() API to get the total count of business days.
The given examples take an optional holiday list and use two predicates to check if a day is a weekend or holiday.
Given both examples use these predicates:
- The first predicate
isWeekend
is used to check if a day is a weekend. - The second predicate
isHoliday
checks if a given day is a holiday.
1. LocalDate.datesUntil() – Java 9
The LocalDate.datesUntil() returns a stream of dates from the start date to the end date. We then check each date in the stream against our two predicates.
public Stream<LocalDate> datesUntil(LocalDate endExclusive) //the end date is exclusive and should not be null.
If the day is not a weekend or a holiday, we consider it a business day. We get all such dates and store them in a List
using stream aggregation method collect()
.
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;
private static List<LocalDate> countBusinessDaysBetween_Java9(final LocalDate startDate,
final LocalDate endDate,
final Optional<List<LocalDate>> holidays) {
// Validate method arguments
if (startDate == null || endDate == null) {
throw new IllegalArgumentException("Invalid method argument(s)
to countBusinessDaysBetween (" + startDate + "," + endDate + "," + holidays + ")");
}
// Predicate 1: Is a given date is a holiday
Predicate<LocalDate> isHoliday = date -> holidays.isPresent()
&& holidays.get().contains(date);
// Predicate 2: Is a given date is a weekday
Predicate<LocalDate> isWeekend = date -> date.getDayOfWeek() == DayOfWeek.SATURDAY
|| date.getDayOfWeek() == DayOfWeek.SUNDAY;
// Iterate over stream of all dates and check each day against any weekday or holiday
List<LocalDate> businessDays = startDate.datesUntil(endDate)
.filter(isWeekend.or(isHoliday).negate())
.collect(Collectors.toList());
return businessDays;
}
Now we can use List.size()
method to get the number of business days, or we can use each date in the list the way we want.
2. Finding Business Days with Stream API
First, we will get the total number of days between two given dates using the ChronoUnit.DAYS.between() API.
Then we get iterate over a stream of all the dates from the start date to the end date until we hit daysBetween
limit, and check each date against our two predicates isHoliday
and isWeekend
.
private static List<LocalDate> countBusinessDaysBetween_Java8(final LocalDate startDate,
final LocalDate endDate,
final Optional<List<LocalDate>> holidays)
{
// Validate method arguments
if (startDate == null || endDate == null) {
throw new IllegalArgumentException("Invalid method argument(s) to
countBusinessDaysBetween (" + startDate
+ "," + endDate + "," + holidays + ")");
}
// Predicate 1: Is a given date is a holiday
Predicate<LocalDate> isHoliday = date -> holidays.isPresent()
&& holidays.get().contains(date);
// Predicate 2: Is a given date is a weekday
Predicate<LocalDate> isWeekend = date -> date.getDayOfWeek() == DayOfWeek.SATURDAY
|| date.getDayOfWeek() == DayOfWeek.SUNDAY;
// Get all days between two dates
long daysBetween = ChronoUnit.DAYS.between(startDate, endDate);
// Iterate over stream of all dates and check each day against any weekday or
// holiday
return Stream.iterate(startDate, date -> date.plusDays(1))
.limit(daysBetween)
.filter(isHoliday.or(isWeekend).negate())
.collect(Collectors.toList());
}
Happy Learning !!