BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Algorithms and Data Structures
.NET 1.1+

Calculate the Number of Business Days in a Range

A common task is to calculate the number of business days that exist within a date range. In most western cultures, these are the days from Monday to Friday and excluding Saturdays and Sundays. The resultant number should also exclude national holidays.

Checking if a Holiday is Within the Date Range

The next private method that we will add to the class is used to determine whether a single holiday affects the calculation. This method returns a Boolean result, with true indicating that the holiday is within the date range and does not fall on a weekend.

Add the following method to the BusinessDaysCalculator class:

private bool HolidayInRange(DateTime startDate, DateTime endDate, DateTime holiday)
{
    return (holiday.Date >= startDate && holiday <= endDate
        && holiday.DayOfWeek != DayOfWeek.Saturday
        && holiday.DayOfWeek != DayOfWeek.Sunday);
}

Counting the Number of Holidays Within the Date Range

The HolidayInRange method is used repeatedly by another private method. The HolidayCount method determines the total number of holidays that affect the calculation. To do so, the method loops through all of the holidays in the array and adds one to a counter each time that the call to HolidayInRange returns true. There is a limitation to this method. If the same date appears twice or more in the holidays array, it will be counted more than once. This can be corrected by ensuring that the array only ever contains unique values.

private int HolidayCount(DateTime startDate, DateTime endDate, DateTime[] holidays)
{
    int holidayCount = 0;
    foreach (DateTime holiday in holidays)
    {
        if (HolidayInRange(startDate, endDate, holiday)) holidayCount++;
    }
    return holidayCount;
}

If you are using a version of the .NET framework that supports Language-Integrated Query (LINQ), you can replace the code in the HolidayCount method with a LINQ expression. The expression below counts the number of holidays that affect the overall calculation. The use of Distinct also ensures that any duplicated holidays are only counted once.

return (from h in holidays
        where HolidayInRange(startDate, endDate, h)
        select h).Distinct().Count();

The Final Calculation

The final task to complete the algorithm is the addition of the CalculateDifference method. This method performs several steps to determine the number of business days in the provided date range. The steps are:

  1. Calculate the difference in days between the two dates. This is achieved by subtracting the start date from the end date. The result of the subtraction is a TimeSpan value containing the number of days in the TotalDays property. The value will include the start but not the end of the range. This will be corrected later to give an inclusive result.
  2. Determine the number of weekends that are in the range by dividing the number of days by seven, discarding any fraction and retaining the integer only. If the day of the week of the end date is before the day of the week of the start date, the weeks value is incremented as an extra weekend exists.
  3. Reduce the difference value to remove the weekends. The difference is lowered by the number of weeks multiplied by two.
  4. Reduce the difference value by the number of holidays in the range.
  5. Add one to the result before returning it to make the value inclusive.
private int CalculateDifference(DateTime startDate, DateTime endDate, DateTime[] holidays)
{
    int difference = (int)(endDate - startDate).TotalDays;
    int weeks = difference / 7;
    if (endDate.DayOfWeek < startDate.DayOfWeek) weeks++;
    difference -= weeks * 2;
    difference -= HolidayCount(startDate, endDate, holidays);
    return difference + 1;
}

Using the Calculator

To test the algorithm we can use the Main method of the program. Add the code below to calculate the number of business days in January 2010, assuming no holidays,

DateTime start = new DateTime(2010,1,1);
DateTime end = new DateTime(2010, 1, 31);
BusinessDaysCalculator calc = new BusinessDaysCalculator();
int days = calc.Calculate(start, end, new DateTime[0]);

Console.WriteLine(days);    // Outputs 21

To use the algorithm and include holidays in the calculation, try the following:

DateTime[] holidays = new DateTime[3];
holidays[0] = new DateTime(2010, 1, 11);
holidays[1] = new DateTime(2010, 1, 12);
holidays[2] = new DateTime(2010, 1, 13);

DateTime start = new DateTime(2010, 1, 1);
DateTime end = new DateTime(2010, 1, 31);
BusinessDaysCalculator calc = new BusinessDaysCalculator();
int days = calc.Calculate(start, end, holidays);

Console.WriteLine(days);    // Outputs 18
10 January 2010