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 ((int)endD.DayOfWeek == 6) calcBusinessDays --;
if ((int)startD.DayOfWeek == 0) calcBusinessDays --;
return calcBusinessDays;
}
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 |