Introduction
In this tip, I provide a code solution for a problem which I couldn't find a good solution for on the web myself. The problem is that in some situations you want to calculate with dates and times without using the weekends. For example, when the company is closed on weekends and you want to calculate how many working days a product is in production.
Background
There are a few examples around which provide us with a method to get the number of working days between two System.DateTime
objects and add a specified number of working days to a System.DateTime
object. Unfortunately these solutions are only precise to days. In many situations, you also want to reckon with hours, minutes and seconds.
Using the Code
I've written two extension methods which apply to System.DateTime
objects. Adding the class found below to your project will automatically make these methods available on your System.DateTime
objects. However this is not always necessary. These methods can also easily be modified to work as normal methods.
using System;
namespace Middelpat.Extensions
{
public static class CalenderExtensions
{
public static TimeSpan SubstractDateExcludingWeekends
(this DateTime startDate, DateTime end)
{
TimeSpan betweenTime = end - startDate;
int numberOfWeekendDays = 0;
if (startDate.DayOfWeek == DayOfWeek.Saturday)
{
betweenTime -= new TimeSpan(1, (23 - startDate.Hour),
(59 - startDate.Minute), (60 - startDate.Second));
}
else if (startDate.DayOfWeek == DayOfWeek.Sunday)
{
betweenTime -= new TimeSpan((23 - startDate.Hour),
(59 - startDate.Minute), (60 - startDate.Second));
}
else if (end.DayOfWeek <
startDate.DayOfWeek && end.DayOfWeek != DayOfWeek.Sunday)
{
numberOfWeekendDays += 2;
}
int betweenDays = betweenTime.Days;
betweenDays = betweenDays % 7 == 6 ? betweenDays += 1 : betweenDays;
numberOfWeekendDays += ((int)((decimal)betweenDays / 7m) * 2);
if (end.DayOfWeek == DayOfWeek.Saturday)
{
betweenTime -= new TimeSpan(end.Hour, end.Minute, end.Second);
}
else if (end.DayOfWeek == DayOfWeek.Sunday)
{
betweenTime -= new TimeSpan(1, end.Hour, end.Minute, end.Second);
}
return betweenTime - new TimeSpan(numberOfWeekendDays, 0, 0, 0);
}
public static DateTime AddTimeSpanExcludingWeekends
(this DateTime startDate, TimeSpan time)
{
DateTime newDate = startDate;
if (startDate.DayOfWeek == DayOfWeek.Saturday)
{
newDate += new TimeSpan(1, (23 - startDate.Hour),
(59 - startDate.Minute), (60 - startDate.Second));
}
else if (startDate.DayOfWeek == DayOfWeek.Sunday)
{
newDate += new TimeSpan((23 - startDate.Hour),
(59 - startDate.Minute), (60 - startDate.Second));
}
int weekDayCount = time.Days;
TimeSpan timeLefAfterLoop = time - new TimeSpan(time.Days, 0 , 0, 0);
for (int i = 0; i < weekDayCount; i++)
{
newDate = newDate.AddDays(1);
if (newDate.DayOfWeek == DayOfWeek.Saturday)
{
newDate = newDate.AddDays(2);
}
}
newDate += timeLefAfterLoop;
if (newDate.DayOfWeek == DayOfWeek.Saturday)
{
newDate = newDate.AddDays(2);
}
else if (newDate.DayOfWeek == DayOfWeek.Sunday)
{
newDate = newDate.AddDays(1);
}
return newDate;
}
}
}
History
- 23-10-2012: Initial version