C#:从cetain日期添加工作日

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

在C#中有类似的东西:

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

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

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

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

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

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

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

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

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

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

这就是你需要的:

更新 :

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

是一个旧post,但有人可能会对处理负面日期的扩展感兴趣。 (我已经重写了@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; } 

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

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