Manipulating date and time values is a common programming problem in many applications. Have you ever wondered how we can calculate the number of weekdays between two dates? Knowing how to do this can be crucial in scheduling, project management, or resource allocation applications. In this article, we analyze some techniques we can use to determine the number of weekdays between two dates in C#. 

To download the source code for this article, you can visit our GitHub repository.

Without further ado, let’s start!

Determine the Number of Weekdays Between Two Dates in C#

We can leverage the DateTime class to calculate the number of weekdays between two dates in C#:

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!
public static int CalculateBusinessDays(DateTime startDate, DateTime endDate)
{
    var weekdays = 0;

    for (var currentDate = startDate; currentDate < endDate; currentDate = currentDate.AddDays(1))
    {
        if (IsWorkDay(currentDate))
        {
            weekdays++;
        }
    }

    return weekdays;
}

 private static bool IsWorkDay(DateTime date)
 {
     return date.DayOfWeek is not DayOfWeek.Saturday
         and not DayOfWeek.Sunday;
 }

Here, we use the DayOfWeek property in the DateTime class to check which day of the week the currentDate value falls on. We add the weekdays value only when we encounter weekdays and ignore weekends. Our implementation has an O(N) time complexity, where N is the number of days between the start and end dates. Therefore, our implementation could have performance issues for large date ranges. 

Also, we can verify that our solution returns accurate results:

var startDate = new DateTime(2024, 1, 1);
var endDate = new DateTime(2024, 1, 15);
var expectedWeekdays = 10;

var actualWeekdays = WorkdaysInCSharpMethods.CalculateBusinessDays(startDate, endDate);

Assert.IsInstanceOfType(actualWeekdays, typeof(int));
Assert.AreEqual(expectedWeekdays, actualWeekdays);

Here, we verify ten weekdays between the 1st and the 15th of January 2024. Besides that, we check whether our CalculateBusinessDays() method returns an integer. 

How to Add Weekdays to a Start Date

Sometimes, we may want to add business days to a start date to get an end date. Let’s implement a solution that helps us accomplish our goal:

public static DateTime AddWorkDays(DateTime startDate, int workDays)
{
    var endDate = startDate;

    while (workDays > 0)
    {
        endDate = endDate.AddDays(1);

        if (IsWorkDay(endDate))
        {
            workDays--;
        }
    }

    return endDate;
}

Here, we initialize endDate with the value in the startDate variable. Next, we iterate while checking whether the endDate value falls on a weekend and decreases the value of workDays if the condition is true. We repeat the process while invoking endDate.AddDays(1) to increment the value of endDate by one until workDays becomes zero. 

Finally, we can verify the method returns accurate results:

var startDate = new DateTime(2024, 1, 1);
var expectedDate = new DateTime(2024, 1, 15);
var daysToAdd = 10;

var actualDate = WorkdaysInCSharpMethods.AddWorkDays(startDate, daysToAdd);

Assert.IsInstanceOfType(actualDate, typeof(DateTime));
Assert.AreEqual(expectedDate, actualDate);

We invoke the AddWorkDays() method and add ten days to the start date to confirm that we get the 15th of January 2024 as the result. 

Determine the Number of Weekdays, Taking Holidays Into Account

Our previous examples assume that we are not considering public holidays that fall on weekdays. For example, Thanksgiving Day falls on Thursday every year. When implementing weekday calculations in HR systems, we may be required to accommodate public holidays in different countries. We can take advantage of .NET-based third-party date libraries such as Nager.Date to accomplish our goal.  

First, let’s write a function that accepts a country code and year as parameters and returns an array of date strings that fall on public holidays:

private static async Task<string[]> GetHolidaysAsync(int year, string countryCode)
{
    HttpClient httpClient = new();
    var url = $"https://date.nager.at/api/v3/PublicHolidays/{year}/{countryCode}";
    var response = await httpClient.GetStringAsync(url);
    var holidays = JArray.Parse(response);
    var holidayDates = new string[holidays.Count];

    for (var i = 0; i < holidays.Count; i++)
    {
        holidayDates[i] = holidays[i]["date"].ToString();
    }

    return holidayDates;
}

Here, we use HttpClient to make a GET request to the API while passing the year and countryCode. Once we get the HTTP response, we use the JArray.Parse() method to load the JSON string into a JArray object. Finally, we read the object’s values and add them to a string array containing holiday dates, which we return as an array of date strings. 

Note that HttpClient is designed for reuse within an application, so declaring it, using it once in a method, and not disposing of it (or implementing a using statement) can be problematic in practice (i.e., lead to socket exhaustion if such a method was called repeatedly).

Therefore, we can modify our previous example to support public holidays:

public static async Task<int> CalculateBusinessDaysExcludingHolidaysAsync(DateTime startDate, DateTime endDate,
                                                                          string countryCode)
 {
     var weekDays = 0;
     var holidaysArray = await GetHolidaysAsync(startDate.Year, countryCode);
     var holidays = new HashSet<string>(holidaysArray); 

     for (var currentDate = startDate.Date; currentDate < endDate.Date;)
     {
         if (IsWorkDay(currentDate))
         {
             var currentDateStr = currentDate.ToString("yyyy-MM-dd");

             if (!holidays.Contains(currentDateStr))
             {
                 weekDays++;
             }
         }

         currentDate = currentDate.AddDays(currentDate.DayOfWeek == DayOfWeek.Friday ? 3 : 1);
     }

     return weekDays;
 }

Here, we add a check to assess whether the currentDate is among the public holidays returned from our GetHolidaysAsync() implementation. Finally, we add three days if currentDate is on a Friday.

Likewise, we can also add workdays to a start date while considering public holidays:

public static async Task<DateTime> AddWorkDaysExcludingHolidaysAsync(DateTime startDate, int workDays,
                                                                     string countryCode)
{
    var endDate = startDate;
    var holidays = await GetHolidaysAsync(startDate.Year, countryCode);

    while (workDays > 0)
    {
        endDate = endDate.AddDays(1);

        if (IsWorkDay(endDate) && !holidays.Contains(endDate.ToString("yyyy-MM-dd")))
        {
            workDays--;
        }
    }

    return endDate;
}

Like our previous example, we iterate while checking whether the endDate value falls on a weekend and not a public holiday and decreases the value of workDays if the conditions are true.  

Conclusion

In this article, we’ve explored how to determine the number of weekdays between two dates in C#. Which technique or library do you prefer when extracting public holidays and why? Let us know in the comments below. 

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!