How can I add business days to the current date in Java?

Here is the modified version to find date calculation.

public  Calendar algorithm2(int businessDays){
    Calendar cal2 = Calendar.getInstance();
    Calendar cal = Calendar.getInstance(); 
    int totalDays= businessDays/5*7;
    int remainder = businessDays % 5;
    cal2.add(cal2.DATE, totalDays); 

    switch(cal.get(Calendar.DAY_OF_WEEK)){
        case 1:
                break;
        case 2: 
                break;
        case 3: 
                if(remainder >3)
                cal2.add(cal2.DATE,2);
                break;
        case 4: 
                if(remainder >2)
                cal2.add(cal2.DATE,2);
                break;
        case 5: 
                if(remainder >1)
                cal2.add(cal2.DATE,2);
                break;
        case 6: 
                if(remainder >1)
                cal2.add(cal2.DATE,2);
                break;
        case 7: 
                if(remainder >1)
                cal2.add(cal2.DATE,1);
                break;
    }

    cal2.add(cal2.DATE, remainder); 
    return cal2;

}

You may want to consider using ObjectLab Kit to do the heavy lifting for you.

Assuming the requirement is simply to return the next business day when the computed date falls on a non-business day:

package bizdays.example;

import java.time.LocalDate;
import java.util.HashSet;
import net.objectlab.kit.datecalc.common.DateCalculator;
import net.objectlab.kit.datecalc.common.DefaultHolidayCalendar;
import net.objectlab.kit.datecalc.common.HolidayHandlerType;
import net.objectlab.kit.datecalc.jdk8.LocalDateKitCalculatorsFactory;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;

public class BizDayTest {
    private DateCalculator<LocalDate> dateCalculator;
    private final LocalDate startDate = LocalDate.of(2009, 12, 23);

    @Before
    public void setUp() {
        HashSet<LocalDate> holidays = new HashSet<LocalDate>();
        holidays.add(LocalDate.of(2009, 12, 25));  // Friday

        DefaultHolidayCalendar<LocalDate> holidayCalendar =
            new DefaultHolidayCalendar<LocalDate>(holidays);

        LocalDateKitCalculatorsFactory.getDefaultInstance()
                .registerHolidays("example", holidayCalendar);
        dateCalculator = LocalDateKitCalculatorsFactory.getDefaultInstance()
                .getDateCalculator("example", HolidayHandlerType.FORWARD);
        dateCalculator.setStartDate(startDate);
    }

    @Test
    public void should_not_change_calendar_start_date_even_after_moving() {
        assertThat(
            dateCalculator.moveByBusinessDays(6).getStartDate(),
            equalTo(startDate));
    }

    @Test
    public void moveByBusinessDays_will_return_24_dec_2009_as_next_business_day() {
        assertThat(
            dateCalculator.moveByBusinessDays(1).getCurrentBusinessDate(),
            equalTo(LocalDate.of(2009, 12, 24)));
    }

    @Test
    public void moveByBusinessDays_will_return_28_dec_2009_as_two_business_days_later() {
        assertThat(
            dateCalculator.moveByBusinessDays(2).getCurrentBusinessDate(),
            equalTo(LocalDate.of(2009, 12, 28)));

    }

    @Test
    public void moveByDays_will_also_return_28_dec_2009_as_two_business_days_later() {
        assertThat(
            dateCalculator.moveByDays(2).getCurrentBusinessDate(),
            equalTo(LocalDate.of(2009, 12, 28)));
    }

    @Test
    public void moveByBusinessDays_will_exclude_25_26_and_27_dec_when_computing_business_days() {
        assertThat(
            dateCalculator.moveByBusinessDays(5).getCurrentBusinessDate(),
            equalTo(LocalDate.of(2009, 12, 31)));
    }


    @Test
    public void moveByDays_will_include_25_26_and_27_dec_when_computing_business_days() {
        assertThat(
            dateCalculator.moveByDays(5).getCurrentBusinessDate(),
            equalTo(LocalDate.of(2009, 12, 28)));
    }
}

The library defaults the working week to be from Monday to Friday, but you can change the defaults by supplying a custom WorkingWeek to DateCalculator's setWorkingWeek().

As shown in the last two examples, moveByDays() includes the weekends when moving the days, whereas moveByBusinessDays() excludes weekends.

The library also allows you to use java.util.Calendar or Joda Time's LocalDate. The examples use JDK8's java.time.LocalDate because it is the preferred way since JDK8.

Edit: Updated examples to use java.time.LocalDate


Use:

public Calendar addBusinessDate(Calendar cal, int numBusinessDays) {
  int numNonBusinessDays = 0;

  for(int i = 0; i < numBusinessDays; i++) {
    cal.add(Calendar.DATE, 1);

    /*
       It's a Canadian/American custom to get the Monday (sometimes Friday) off
       when a holiday falls on a weekend.
    */
    for(int j = 0; j < holidays; j++) { //holidays is list of dates
      if(cal.getTime() == (Date)holidays.get(j)) {
        numNonBusinessDays++;
      }
    }

    if(cal.get(Calendar.DAY_OF_WEEK) == 1 ||
       cal.get(Calendar.DAY_OF_WEEK) == 7) {
      numNonBusinessDays++;
    }
  }

  if(numNonBusinessDays > 0) {
    cal.add(Calendar.DATE, numNonBusinessDays);
  }

  return cal;
}

You'd have to populate a list of dates in order to handle holidays. There's common ones like New Years, but Thanksgiving is different between Canada & the US for instance. Also mind that holidays can fall on a weekend, so the weekend becomes a 3 day weekend.

Reference:

  • Calendar
  • Calendar Constant Values

PS: There isn't really a need to return the Calendar instance if you are updating the value as in the example. But it is valid if you want to create a separate Calendar instance, use:

public Calendar addBusinessDate(Calendar cal, int numBusinessDays) {
  Calendar cal2 = Calendar.getInstance();
  cal2.setTime(cal.getTime());

  int numNonBusinessDays = 0;

  for(int i = 0; i < numBusinessDays; i++) {
    cal2.add(Calendar.DATE, 1);

    /*
       It's a Canadian/American custom to get the Monday (sometimes Friday) off
       when a holiday falls on a weekend.
    */
    for(int j = 0; j < holidays; j++) { //holidays is list of dates
      if(cal2.getTime() == (Date)holidays.get(j)) {
        numNonBusinessDays++;
      }
    }

    if(cal2.get(Calendar.DAY_OF_WEEK) == 1 ||
       cal2.get(Calendar.DAY_OF_WEEK) == 7) {
      numNonBusinessDays++;
    }
  }

  if(numNonBusinessDays > 0) {
    cal2.add(Calendar.DATE, numNonBusinessDays);
  }

  return cal2;
}

//supports negative numbers too.

private Calendar addBusinessDay(final Calendar cal, final Integer numBusinessDays)
{
    if (cal == null || numBusinessDays == null || numBusinessDays.intValue() == 0)
    {
        return cal;
    }
    final int numDays = Math.abs(numBusinessDays.intValue());
    final int dateAddition = numBusinessDays.intValue() < 0 ? -1 : 1;//if numBusinessDays is negative
    int businessDayCount = 0;
    while (businessDayCount < numDays)
    {
        cal.add(Calendar.DATE, dateAddition);

        //check weekend
        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
        {
            continue;//adds another day
        }

        //check holiday
        if (isHoliday(cal))//implement isHoliday yourself
        {
            continue;//adds another day
        }

        businessDayCount++;
    }
    return cal;
}

Tags:

Algorithm

Java