开发者

Counting regular working days in a given period of time

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 need to exclude saturdays and sundays when I use it on my computations.

I need an algorithm something like t开发者_JAVA技巧his in C#:

    int GetRegularWorkingDays(DateTime startDate, DateTime endDate)
    {

       int nonWorkingDays = ((endDate - startDate) % 7) * 2;

       return (endDate - startDate) - nonWorkingDays;
    }

I know my draft is way way off :(. Thanks in advance. =)

PS: Guys please up-vote the best/fastest/most efficient answer below. Thanks =)


Check out this example on Code Project that uses a very efficient way that doesn't involve any looping ;)

It uses this alogrithm:

  1. Calculate the number of time span in terms of weeks. Call it, W.
  2. Deduct the first week from the number of weeks. W= W-1
  3. Multiply the number of weeks with the number of working days per week. Call it, D.
  4. Find out the holidays during the specified time span. Call it, H.
  5. Calculate the days in the first week. Call it, SD.
  6. Calculate the days in the last week. Call it, ED.
  7. Sum up all the days. BD = D + SD + ED - H.


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;
}


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;
    }


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);
    }
}


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;
}


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;
}


int count = 0;
switch (dateTimePicker2.Value.DayOfWeek.ToString())
{
    case "Saturday": count--; break;
    case "Sunday": count--; break;
    default:break;
}
switch (dateTimePicker3.Value.DayOfWeek.ToString())
{
    case "Saturday": count--; break;
    case "Sunday": count--; break;
    default:break;
}
if (count == -2)
    count = -1;
int weeks = t.Days / 7;
int daycount =count+ t.Days - (2 * weeks)+1;
label7.Text = "No of Days : " + daycount.ToString();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜