How do I calculate days between two dates excluding weekends and holidays?

The code snippet below shows you a simple way to calculate days between two dates excluding weekends and holidays. As an example, you can use this function for calculating work days. The snippet utilize the java.time API and the Stream API to calculate the value.

What we do in the code below can be described as the following:

  • Create a list of holidays. The dates might be read from a database or a file.
  • Define filter Predicate for holidays.
  • Define filter Predicate for weekends.
  • These predicates will be use for filtering the days between two dates.
  • Define the startDate and the endDate to be calculated.
  • Using Stream.iterate() we iterate the dates, filter it based on the defined predicates.
  • Finally, we get the result as list.
  • The actual days between is the size of the list, workDays.size().
package org.kodejava.datetime;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class DaysBetweenDates {
    public static void main(String[] args) {
        List<LocalDate> holidays = new ArrayList<>();
        holidays.add(LocalDate.of(2022, Month.DECEMBER, 26));
        holidays.add(LocalDate.of(2023, Month.JANUARY, 2));

        Predicate<LocalDate> isHoliday = holidays::contains;
        Predicate<LocalDate> isWeekend = date -> date.getDayOfWeek() == DayOfWeek.SATURDAY
                || date.getDayOfWeek() == DayOfWeek.SUNDAY;

        LocalDate startDate = LocalDate.of(2022, Month.DECEMBER, 23);
        LocalDate endDate = LocalDate.of(2023, Month.JANUARY, 3);
        System.out.println("Start date = " + startDate);
        System.out.println("End date   = " + endDate);

        // Days between startDate inclusive and endDate exclusive
        long daysBetween = ChronoUnit.DAYS.between(startDate, endDate);
        System.out.println("Days between = " + daysBetween);

        List<LocalDate> workDays = Stream.iterate(startDate, date -> date.plusDays(1))
                .limit(daysBetween)
                .filter(isHoliday.or(isWeekend).negate())
                .toList();

        long actualDaysBetween = workDays.size();
        System.out.println("Actual days between = " + actualDaysBetween);
    }
}

Running the code snippet above give us the following result:

Start date = 2022-12-23
End date   = 2023-01-03
Days between = 11
Actual days between = 5
Wayan

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.