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

需要一些帮助。 我需要计算一个特定日期的正常工作日,例如,在我们国家,我们星期一到星期五有5个正常工作日,然后在代码中我需要排除星期六和星期日,当我在我的计算中使用它时。

我需要在C#中使用类似的算法:

int GetRegularWorkingDays(DateTime startDate, DateTime endDate) { int nonWorkingDays = ((endDate - startDate) % 7) * 2; return (endDate - startDate) - nonWorkingDays; } 

我知道我的选秀很开心:(。提前致谢。=)

PS:伙计们请在下面投票选出最好/最快/最有效的答案。 谢谢=)

查看代码项目中的这个示例,它使用一种不涉及任何循环的非常有效的方法;)

它使用这种算法:

  1. 以周为单位计算时间跨度。 叫它,W。
  2. 从周数减去第一周。 W = W-1
  3. 将周数乘以每周的工作日数。 叫它,D。
  4. 在指定的时间跨度内找出假期。 叫它,H.
  5. 计算第一周的天数。 叫它,SD。
  6. 计算上周的天数。 叫它,ED。
  7. 总结所有的日子。 BD = D + SD +ED H。

一衬!

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

或更高效:

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

我写了一个类型扩展器,允许我在给定日期添加(或减去)工作日。 也许这会对你有所帮助。 效果很好,所以如果这对你有所帮助,请投票给我的post。

  ///  /// Adds weekdays to date ///  /// DateTime to add to /// Number of weekdays to add /// DateTime 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; } 

不是很快,但这可以解决问题:

 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 Range(DateTime start, DateTime end) { while (start <= end) { yield return start; start = start.AddDays(1); } } 

您可以尝试一种简单的方法来计算天数。 如果这通常是在几个月而不是几年的时间段内完成,并且不会被重复调用,那么这不会仅仅是一次性能打击。

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

您可以使用时间线辅助类来完成此操作 – 此类还允许其他时间间隔:

 public class TimeLine { public static IEnumerable CreateTimeLine(DateTime start, TimeSpan interval) { return TimeLine.CreateTimeLine(start, interval, DateTime.MaxValue); } public static IEnumerable 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); } } 

要解决您的问题,您可以执行以下操作:

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

此时间线类可用于任何间隔的任何连续时间线。

获得工作日的简单方法:

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