need some help. I need to count regular working days for a given date period, for example, in our country, we have 5 regular working days monday to friday, then in code i ne
Not very fast, but this will do the trick:
int GetRegularWorkingDays(DateTime start, DateTime end)
{
return (
from day in Range(start, end)
where day.DayOfWeek != DayOfWeek.Saturday
where day.DayOfWeek != DayOfWeek.Sunday
select day).Count();
}
IEnumerable<DateTime> Range(DateTime start, DateTime end)
{
while (start <= end)
{
yield return start;
start = start.AddDays(1);
}
}
One-liner!
int workingDays = Enumerable.Range(0, Convert.ToInt32(endDate.Subtract(startDate).TotalDays)).Select(i=>new [] { DayOfWeek.Saturday, DayOfWeek.Sunday }.Contains(startDate.AddDays(i).DayOfWeek) ? 0 : 1).Sum();
Or more efficient:
DayOfWeek currDay = startDate.DayOfWeek;
int nonWorkingDays = 0;
foreach(var i in Enumerable.Range(0, Convert.ToInt32(endDate.Subtract(startDate).TotalDays)))
{
if(currDay == DayOfWeek.Sunday || currDay == DayOfWeek.Saturday)
nonWorkingDays++;
if((int)++currDay > 6) currDay = (DayOfWeek)0;
}
You could do it with a time line helper class - this class also allows for other intervals:
public class TimeLine
{
public static IEnumerable<DateTime> CreateTimeLine(DateTime start, TimeSpan interval) {
return TimeLine.CreateTimeLine(start, interval, DateTime.MaxValue);
}
public static IEnumerable<DateTime> CreateTimeLine(DateTime start, TimeSpan interval, DateTime end) {
var currentVal = start;
var endVal = end.Subtract(interval);
do {
currentVal = currentVal.Add(interval);
yield return currentVal;
} while (currentVal <= endVal);
}
}
To solve your problem you can do the following:
var workingDays = TimeLine.CreateTimeLine(DateTime.Now.Date, TimeSpan.FromDays(1), DateTime.Now.Date.AddDays(30))
.Where(x => x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday);
var noOfWorkingDays = workingDays.Count();
This time line class can be used for any continuous time line of any interval.
Simple method to get work days:
int GetRegularWorkingDays(DateTime startDate, DateTime endDate)
{
int total = 0;
if (startDate < endDate)
{
var days = endDate - startDate;
for( ; startDate < endDate; startDate = startDate.AddDays(1) )
{
switch(startDate.DayOfWeek)
{
case DayOfWeek.Saturday :
case DayOfWeek.Sunday :
break;
default:
total++;
break;
}
}
}
return total;
}
You could try a simple method of just counting the days. If this is usually done for periods of time like months and not years and isn't called repeatedly then this will not be a performance hit to just walk it.
int GetWorkingDays(DateTime startDate, DateTime endDate)
{
int count = 0;
for (DateTime currentDate = startDate; currentDate < endDate; currentDate = currentDate.AddDays(1))
{
if (currentDate.DayOfWeek == DayOfWeek.Sunday || currentDate.DayOfWeek == DayOfWeek.Saturday)
{
continue;
}
count++;
}
return count;
}
I wrote a type extender to allow me to add (or subtract) weekdays to a given date. Maybe this will help you. Works great, so please vote for my post if this helped you.
/// <summary>
/// Adds weekdays to date
/// </summary>
/// <param name="value">DateTime to add to</param>
/// <param name="weekdays">Number of weekdays to add</param>
/// <returns>DateTime</returns>
public static DateTime AddWeekdays(this DateTime value, int weekdays)
{
int direction = Math.Sign(weekdays);
int initialDayOfWeek = Convert.ToInt32(value.DayOfWeek);
//---------------------------------------------------------------------------
// if the day is a weekend, shift to the next weekday before calculating
if ((value.DayOfWeek == DayOfWeek.Sunday && direction < 0)
|| (value.DayOfWeek == DayOfWeek.Saturday && direction > 0))
{
value = value.AddDays(direction * 2);
weekdays += (direction * -1); // adjust days to add by one
}
else if ((value.DayOfWeek == DayOfWeek.Sunday && direction > 0)
|| (value.DayOfWeek == DayOfWeek.Saturday && direction < 0))
{
value = value.AddDays(direction);
weekdays += (direction * -1); // adjust days to add by one
}
//---------------------------------------------------------------------------
int weeksBase = Math.Abs(weekdays / 5);
int addDays = Math.Abs(weekdays % 5);
int totalDays = (weeksBase * 7) + addDays;
DateTime result = value.AddDays(totalDays * direction);
//---------------------------------------------------------------------------
// if the result is a weekend, shift to the next weekday
if ((result.DayOfWeek == DayOfWeek.Sunday && direction > 0)
|| (result.DayOfWeek == DayOfWeek.Saturday && direction < 0))
{
result = result.AddDays(direction);
}
else if ((result.DayOfWeek == DayOfWeek.Sunday && direction < 0)
|| (result.DayOfWeek == DayOfWeek.Saturday && direction > 0))
{
result = result.AddDays(direction * 2);
}
//---------------------------------------------------------------------------
return result;
}