C#:从特定日期开始添加工作日

时间:2010-09-15 12:58:20

标签: c# algorithm datetime

我这样做很麻烦。我正在创建一个在特定日期添加工作日的方法。 例如,我想在2010年9月15日(星期三)之前增加3个工作日,该方法将于9月20日(下周一周一)返回。它无视星期六和星期日,因为它的非工作日..

在C#中有类似的东西:

DateTime AddWorkingDays(DateTime specificDate, int workingDaysToAdd)
{
   return specificDate + (workingDaysToAdd - (all saturdays and sundays))
}

我不考虑计算上的特殊假期,我只是想在星期六和星期日之外添加日期..提前感谢! =)

6 个答案:

答案 0 :(得分:18)

如果你不需要考虑假期,我建议你这样做:

public static DateTime AddWorkingDays(DateTime specificDate,
                                      int workingDaysToAdd)
{
    int completeWeeks = workingDaysToAdd / 5;
    DateTime date = specificDate.AddDays(completeWeeks * 7);
    workingDaysToAdd = workingDaysToAdd % 5;
    for (int i = 0; i < workingDaysToAdd; i++)
    {
        date = date.AddDays(1);
        while (!IsWeekDay(date))
        {
            date = date.AddDays(1);
        }
    }
    return date;
}

private static bool IsWeekDay(DateTime date)
{
    DayOfWeek day = date.DayOfWeek;
    return day != DayOfWeek.Saturday && day != DayOfWeek.Sunday;
}

效率低,但易于理解。对于高效版本,您可以计算出之前要添加的完整周数,但是可以从任何“当前星期几”和“剩余工作日添加”到“实际<的数量”进行映射/ em>天添加“。然后你可以计算出要添加的总天数,并在一次通话中完成。

编辑:就效率低下而言......它真的不是非常坏。它只会执行手动“这是一个周末”检查长达4天,这也不算太糟糕。特别是,尽管igor(发布时的当前)声称,它比他的方法更快,尽管有缺陷的基准;)

请注意,它可能还没有处理负输入 - 我没有检查过。

我正在使用的方法背后的原因之一是它不依赖于我或代码阅读器知道DayOfWeek枚举中的值是什么。我不在乎它是0-6,1-7,周一至周日,周六周五......或者即使有完全奇怪的价值观。我只比较相等,这使代码更“明显正确”。

答案 1 :(得分:1)

一种很酷的方式(我认为)是在扩展方法中,如:

public static class DateTimeExtensions
{
    public static DateTime AddWorkingDays(this DateTime self, int days)
    {
        self = self.AddDays(days);
        while (self.DayOfWeek == DayOfWeek.Saturday || self.DayOfWeek == DayOfWeek.Sunday)
        {
            self = self.AddDays(1);
        }

        return self;
    }
}

所以你的最终代码如下:

specificDate.AddWorkingDays(3);

答案 2 :(得分:0)

以下是您的需求:

已更新:

public static DateTime AddWeekdays(DateTime start, int days)
    {
        int remainder = days % 5;
        int weekendDays = (days / 5) * 2;

        DateTime end = start.AddDays(remainder);

        if (start.DayOfWeek == DayOfWeek.Saturday && days > 0)
        {
            // fix for saturday.
            end = end.AddDays(-1);
        }

        if (end.DayOfWeek == DayOfWeek.Saturday && days > 0)
        {
            // add two days for landing on saturday
            end = end.AddDays(2);
        }
        else if (end.DayOfWeek < start.DayOfWeek)
        {
            // add two days for rounding the weekend
            end = end.AddDays(2);
        }

        // add the remaining days
        return end.AddDays(days + weekendDays - remainder);
    }

答案 3 :(得分:0)

int foundWorkingDays = 0;
while (foundWorkingDays < workingDaysToAdd)
{ 
  specificDate= specificDate.AddDays(1); 
  if(specificDate.DayOfWeek != DayOfWeek.Sunday && specificDate.DayOfWeek != DayOfWeek.Saturday)
     foundWorkingDays++;

}
return specificDate;

<强>增加:

class Program
    {

        public static DateTime AddWorkingDays(DateTime specificDate,
                                      int workingDaysToAdd)
        {
            int completeWeeks = workingDaysToAdd / 5;
            DateTime date = specificDate.AddDays(completeWeeks * 7);
            workingDaysToAdd = workingDaysToAdd % 5;
            for (int i = 0; i < workingDaysToAdd; i++)
            {
                date = date.AddDays(1);
                while (!IsWeekDay(date))
                {
                    date = date.AddDays(1);
                }
            }
            return date;
        }

        private static bool IsWeekDay(DateTime date)
        {
            DayOfWeek day = date.DayOfWeek;
            return day != DayOfWeek.Saturday && day != DayOfWeek.Sunday;
        }

        public static DateTime MyAddWorkingDays(DateTime specificDate,
                                      int workingDaysToAdd)
        {
            int foundWorkingDays = 0;
            while (foundWorkingDays < workingDaysToAdd)
            {
                specificDate = specificDate.AddDays(1);
                if (specificDate.DayOfWeek != DayOfWeek.Sunday && specificDate.DayOfWeek != DayOfWeek.Saturday)
                    foundWorkingDays++;

            }
            return specificDate;
        }


        static void Main(string[] args)
        {

            DateTime specificDate = DateTime.Now;

            Stopwatch globalTimer = Stopwatch.StartNew();
            Console.WriteLine(AddWorkingDays(specificDate, 300));  // 100000 :)
            globalTimer.Stop();
            Console.WriteLine(globalTimer.ElapsedMilliseconds);

            globalTimer = Stopwatch.StartNew();
            Console.WriteLine(MyAddWorkingDays(specificDate, 300)); // 100000 :)
            globalTimer.Stop();
            Console.WriteLine(globalTimer.ElapsedMilliseconds);



            Console.ReadLine();
        }
    }

答案 4 :(得分:0)

是一个旧帖子,但有人可能对处理负面日期的扩展感兴趣。 (我已经重写了@Jon回答)

    public static DateTime AddWeekDays(this DateTime start, int days)
    {
        int direction = Math.Sign(days);

        int completeWeeks = days / 5;
        int remaining = days % 5;

        DateTime end = start.AddDays(completeWeeks * 7);

        for (int i = 0; i < remaining * direction; i++)
        {
            end = end.AddDays(direction * 1);
            while (!IsWeekDay(end))
            {
                end = end.AddDays(direction * 1);
            }
        }
        return end;
    }

    private static bool IsWeekDay(DateTime date)
    {
        DayOfWeek day = date.DayOfWeek;
        return day != DayOfWeek.Saturday && day != DayOfWeek.Sunday;
    }

答案 5 :(得分:0)

在我看来,这是最干净的方式:

public static DateTime AddWorkingDays(DateTime date, int daysToAdd)
{
    while (daysToAdd > 0)
    {
        date = date.AddDays(1);

        if (date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday) daysToAdd -= 1;
    }

    return date;
}