简体   繁体   English

计算给定时间内的正常工作日

[英]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.我需要计算给定日期期间的正常工作日,例如,在我们国家,我们周一到周五有 5 个正常工作日,然后在代码中,当我在计算中使用它时,我需要排除周六和周日。

I need an algorithm something like this in C#:我需要在 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. PS:伙计们,请为下面的最佳/最快/最有效的答案投票。 Thanks =)谢谢=)

Check out this example on Code Project that uses a very efficient way that doesn't involve any looping ;)在 Code Project 上查看此示例,该示例使用了一种不涉及任何循环的非常有效的方式;)

It uses this alogrithm:它使用这个算法:

  1. Calculate the number of time span in terms of weeks.以周为单位计算时间跨度数。 Call it, W.叫它,W。
  2. Deduct the first week from the number of weeks.从周数中减去第一周。 W= W-1 W=W-1
  3. Multiply the number of weeks with the number of working days per week.将周数乘以每周的工作日数。 Call it, D.叫它,D。
  4. Find out the holidays during the specified time span.找出指定时间跨度内的假期。 Call it, H.叫它,H。
  5. Calculate the days in the first week.计算第一周的天数。 Call it, SD.叫它,SD。
  6. Calculate the days in the last week.计算上周的天数。 Call it, ED.叫它,ED。
  7. Sum up all the days.总结一下所有的日子。 BD = D + SD + ED - H. 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;
    }

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM