HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Getting the business day of the month

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thebusinessgettingmonthday

Problem

I'm working on figuring out what the current 'business' day of the month it is. For instance, if it's the 20th, but there are 3 weekends, it would be the 14th business day of the month.

Is there a better way of doing this?

var first = DateTime.Today.FirstDayOfMonth();
var businessDayOfMonth = 0;
for (var i = first; i <= DateTime.Today; i = i.AddDays(1))
{
    if (i.DayOfWeek != DayOfWeek.Saturday && i.DayOfWeek != DayOfWeek.Sunday) 
        businessDayOfMonth++;
}

Solution

As explained in comments (in which I pointed out a few possible edge cases), even though it's not optimized in terms of performance, this is about as clear as it gets.

A more clever algorithm - calculating the number of weekdays without iterating through all of them - is probably possible, but I bet it would be much less readable. If performance isn't a concern at this point, I'd leave it.

You could maybe replace the loop with a LINQ-based solution.

int WhichWorkingDay(DateTime day)
{
    // edge cases
    switch (day.DayOfWeek)
    {
        case DayOfWeek.Saturday:
            return day.Day > 1
                // Friday the day before
                ? WhichWorkingDay(day.AddDays(-1))
                // or next Monday if previous Friday was on last month
                : WhichWorkingDay(day.AddDays(2));
        // analogically here
        case DayOfWeek.Sunday:
            return day.Day > 2
                ? WhichWorkingDay(day.AddDays(-2))
                : WhichWorkingDay(day.AddDays(1));
    }

    // or you could inline it, obviously
    Func isWorkingDay = d => d.DayOfWeek != DayOfWeek.Saturday 
        && d.DayOfWeek != DayOfWeek.Sunday;

    return Enumerable
        .Range(1, day.Day)
        .Select(d => new DateTime(day.Year, day.Month, d))
        .Count(isWorkingDay);
}

Code Snippets

int WhichWorkingDay(DateTime day)
{
    // edge cases
    switch (day.DayOfWeek)
    {
        case DayOfWeek.Saturday:
            return day.Day > 1
                // Friday the day before
                ? WhichWorkingDay(day.AddDays(-1))
                // or next Monday if previous Friday was on last month
                : WhichWorkingDay(day.AddDays(2));
        // analogically here
        case DayOfWeek.Sunday:
            return day.Day > 2
                ? WhichWorkingDay(day.AddDays(-2))
                : WhichWorkingDay(day.AddDays(1));
    }

    // or you could inline it, obviously
    Func<DateTime, bool> isWorkingDay = d => d.DayOfWeek != DayOfWeek.Saturday 
        && d.DayOfWeek != DayOfWeek.Sunday;

    return Enumerable
        .Range(1, day.Day)
        .Select(d => new DateTime(day.Year, day.Month, d))
        .Count(isWorkingDay);
}

Context

StackExchange Code Review Q#124762, answer score: 4

Revisions (0)

No revisions yet.