Work (business) days calculations with C#
If you think it’s a decent solution vote for it! :)
Work days between 2 dates:
public static double GetBusinessDays(DateTime startD, DateTime endD)
{
double calcBusinessDays =
1 + ((endD-startD).TotalDays * 5 –
(startD.DayOfWeek-endD.DayOfWeek) * 2) / 7;
if (endD.DayOfWeek == DayOfWeek.Saturday) calcBusinessDays –;
if (startD.DayOfWeek == DayOfWeek.Sunday) calcBusinessDays –;
return calcBusinessDays;
}
Note 1: Some changes are made to comply with the changes made by admins of StackOverflow.com site. They did removed unnecessary cast to int.
Note 2: Another useful input from the same site: Just to remark, with the ‘1+’ it assumes start of first day until end of last day, without the ‘1+’ it assumes end of first day until end of last day. Took me a while to figure that out, since I was assuming start of first day until start of last day, which made more sense to me. – Jeffry van de Vuurst Oct 23 ’15 at 9:21
Note 3: The code is relying on the fact that by default in C# (int)DayOfWeek.Saturday is 6 and (int)DayOfWeek.Sunday is 0. This option might be different in your region so the code should be refactored accordingly. Looks like both “ifs” could be removed if Monday would be 0 (if week starts Monday). Need to be tested though.
Add work days to a start date:
DateTime startD = new DateTime(2000, 5, 28);
double businessDays = 2300;
int DoW = (int)startD.DayOfWeek;
double temp = businessDays + DoW + 1;
if (DoW != 0) temp –;
DateTime calcendD = startD.AddDays(
Math.Floor(temp / 5)*2-DoW + temp
– 2* Convert.ToInt32(temp % 5 == 0)) ;
What is the logic behind. Could you pls explain?
thanks,
burak.
burak ozdogan - March 25, 2010 at 1:57 pm |
I got that formula after simplifying more complex expression so I don’t know the meanings of the multiplyers. The initial formula was just math expression that anybody can construct if they have basic logic skills and familiar with concept of modulus.
alecpojidaev - March 25, 2010 at 2:16 pm |
The above code fragment does not even compile, let alone calculate the figure suggested.
Rachel - October 15, 2010 at 3:09 pm |
It’s working. The WordPress site is replacing the minus sign with something different when spaces are from both sides of the minus sign. I’ve removed spaces and now copy paste won’t get you into troubles anymore. Anyway thanks.
The downside of that fix is this post won’t be serving as a test for people’s basic troubleshooting skills anylonger :P
alecpojidaev - October 15, 2010 at 4:17 pm |
Very well done.
I tried it for each month of 2010, and it is good.
Here the convert I used in VB.NET :
Public Shared Function GetBusinessDays(ByVal startD As DateTime, ByVal endD As DateTime) As Double
Dim calcBusinessDays As Double = 1 + ((endD - startD).TotalDays * 5 - (startD.DayOfWeek - endD.DayOfWeek) * 2) / 7
If CInt(endD.DayOfWeek) = 6 Then calcBusinessDays -= 1
If CInt(startD.DayOfWeek) = 0 Then calcBusinessDays -= 1
Return calcBusinessDays
End Function
Thanks
dominique Gratpain - October 15, 2010 at 6:42 pm |
Thank you.
alecpojidaev - October 15, 2010 at 6:58 pm |
It’s probably prudent to use a Math.Floor around TotalDays… I would expect a whole number of business days. Especially useful when I need to multiply by the (average/expected) number of hours worked per day.
double calcBusinessDays =
1 + (Math.Floor((endD-startD).TotalDays) * 5 –
(startD.DayOfWeek-endD.DayOfWeek) * 2) / 7;
Corin - March 27, 2011 at 11:46 pm |
No need to use any rounding function here. There will be no reminder after division operation. That is some little math magic for you.
But using rounding function as it is in your example is especially pointless (its impossible to get “not round” figures as a result of multiplication/substraction of whole numbers)
alecpojidaev - March 28, 2011 at 1:25 pm |
Thanks alec… it works like a charm!!!
Gunzino - April 11, 2011 at 1:14 pm |
This is a nice, elegant solution. Wrote up some unit tests to verify it and feel good about it. Thanks man!
Mike Johnson - May 3, 2011 at 4:40 pm |
why adding one work day in your second part “Add work days to a start date” gives the same date as a result?
serop - November 10, 2011 at 5:55 pm |
Fixed
alecpojidaev - November 10, 2011 at 7:37 pm |
First of all, great functions!
Just wondering if you knew of a formula for work days plus Saturdays (M-Sa)? I’ve altered the work days between two dates as follows:
public static double GetBusinessDays(DateTime startD, DateTime endD)
{
double calcBusinessDays =
1 + ((endD-startD).TotalDays * 6 –
(startD.DayOfWeek-endD.DayOfWeek)) / 7;
if ((int)startD.DayOfWeek == 0) calcBusinessDays –;
return calcBusinessDays;
}
My initial testing seems to be positive. Any feedback would be greatly appreciated. Thanks
CH - January 12, 2012 at 9:08 pm |
Made up this ColdFusion Function from this thread. Helped me a lot, thanks! Changes that i’ve made:
> Named it “workingDateDiff”, according to ColdFusion’s built-in “dateDiff” function.
> Used ColdFusions built-in “local”-scope for functions (also re-initializing it for older CF-Versions).
> Since ColdFusions “dayOfWeek”-function returns values from 1 to 7 (other than C# 0 to 6), I changed that too.
schwarzboris - February 12, 2013 at 2:32 pm |
The day-adding function is good but doesn’t quite work when subtracting. For example, adding 5 days to 2015-12-01 gives 2015-12-08, but adding -5 days to 2015-12-08 doesn’t give 2015-12-01.
I’ve fixed this bug in my implementation at https://gist.github.com/batterseapower/586a925a34ba2a85f51a (assumes you have epoch dates as from e.g. the Java 8 LocalDate class)
batterseapower - December 2, 2015 at 10:32 pm |