AddBusinessDays和GetBusinessDays

我需要find2个完美的完整实现

public static DateTime AddBusinessDays(this DateTime date, int days) { // code here } and public static int GetBusinessDays(this DateTime start, DateTime end) { // code here } 

O(1)更好(没有循环)。

编辑:工作日我的意思是工作日(星期一,星期二,星期三,星期四,星期五)。 没有假期,只是周末排除在外。

我已经有一些丑陋的解决scheme似乎工作,但我不知道是否有优雅的方式来做到这一点。 谢谢


这是我迄今写的。 它在所有情况下都能正常工作,并且也能做到负面 仍然需要一个GetBusinessDays实现

 public static DateTime AddBusinessDays(this DateTime startDate, int businessDays) { int direction = Math.Sign(businessDays); if(direction == 1) { if(startDate.DayOfWeek == DayOfWeek.Saturday) { startDate = startDate.AddDays(2); businessDays = businessDays - 1; } else if(startDate.DayOfWeek == DayOfWeek.Sunday) { startDate = startDate.AddDays(1); businessDays = businessDays - 1; } } else { if(startDate.DayOfWeek == DayOfWeek.Saturday) { startDate = startDate.AddDays(-1); businessDays = businessDays + 1; } else if(startDate.DayOfWeek == DayOfWeek.Sunday) { startDate = startDate.AddDays(-2); businessDays = businessDays + 1; } } int initialDayOfWeek = (int)startDate.DayOfWeek; int weeksBase = Math.Abs(businessDays / 5); int addDays = Math.Abs(businessDays % 5); if((direction == 1 && addDays + initialDayOfWeek > 5) || (direction == -1 && addDays >= initialDayOfWeek)) { addDays += 2; } int totalDays = (weeksBase * 7) + addDays; return startDate.AddDays(totalDays * direction); } 

您的第一个function的最新尝试:

 public static DateTime AddBusinessDays(DateTime date, int days) { if (days < 0) { throw new ArgumentException("days cannot be negative", "days"); } if (days == 0) return date; if (date.DayOfWeek == DayOfWeek.Saturday) { date = date.AddDays(2); days -= 1; } else if (date.DayOfWeek == DayOfWeek.Sunday) { date = date.AddDays(1); days -= 1; } date = date.AddDays(days / 5 * 7); int extraDays = days % 5; if ((int)date.DayOfWeek + extraDays > 5) { extraDays += 2; } return date.AddDays(extraDays); } 

第二个函数Ge​​tBusinessDays可以实现如下:

 public static int GetBusinessDays(DateTime start, DateTime end) { if (start.DayOfWeek == DayOfWeek.Saturday) { start = start.AddDays(2); } else if (start.DayOfWeek == DayOfWeek.Sunday) { start = start.AddDays(1); } if (end.DayOfWeek == DayOfWeek.Saturday) { end = end.AddDays(-1); } else if (end.DayOfWeek == DayOfWeek.Sunday) { end = end.AddDays(-2); } int diff = (int)end.Subtract(start).TotalDays; int result = diff / 7 * 5 + diff % 7; if (end.DayOfWeek < start.DayOfWeek) { return result - 2; } else{ return result; } } 

使用stream利date时间 :

 var now = DateTime.Now; var dateTime1 = now.AddBusinessDays(3); var dateTime2 = now.SubtractBusinessDays(5); 

内部代码如下

  /// <summary> /// Adds the given number of business days to the <see cref="DateTime"/>. /// </summary> /// <param name="current">The date to be changed.</param> /// <param name="days">Number of business days to be added.</param> /// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns> public static DateTime AddBusinessDays(this DateTime current, int days) { var sign = Math.Sign(days); var unsignedDays = Math.Abs(days); for (var i = 0; i < unsignedDays; i++) { do { current = current.AddDays(sign); } while (current.DayOfWeek == DayOfWeek.Saturday || current.DayOfWeek == DayOfWeek.Sunday); } return current; } /// <summary> /// Subtracts the given number of business days to the <see cref="DateTime"/>. /// </summary> /// <param name="current">The date to be changed.</param> /// <param name="days">Number of business days to be subtracted.</param> /// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns> public static DateTime SubtractBusinessDays(this DateTime current, int days) { return AddBusinessDays(current, -days); } 

我创build了一个扩展,允许您添加或减less工作日。 使用负数的businessDays减去。 我认为这是相当优雅的解决scheme。 它似乎在所有情况下工作。

 namespace Extensions.DateTime { public static class BusinessDays { public static System.DateTime AddBusinessDays(this System.DateTime source, int businessDays) { var dayOfWeek = businessDays < 0 ? ((int)source.DayOfWeek - 12) % 7 : ((int)source.DayOfWeek + 6) % 7; switch (dayOfWeek) { case 6: businessDays--; break; case -6: businessDays++; break; } return source.AddDays(businessDays + ((businessDays + dayOfWeek) / 5) * 2); } } } 

例:

 using System; using System.Windows.Forms; using Extensions.DateTime; namespace AddBusinessDaysTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); label1.Text = DateTime.Now.AddBusinessDays(5).ToString(); label2.Text = DateTime.Now.AddBusinessDays(-36).ToString(); } } } 

对我来说,我必须有一个解决scheme,可以跳过周末,不pipe是消极的还是积极的。 我的标准是,如果前进并在周末降落,则需要提前至星期一。 如果它回来并在周末降落,它将不得不跳到星期五。

例如:

  • 周三 – 3个工作日=上周五
  • 周三+ 3个工作日=星期一
  • 周五 – 7个工作日=上周三
  • 星期二 – 5个工作日=上个星期二

那么你明白了;)

我最终写了这个扩展类

 public static partial class MyExtensions { public static DateTime AddBusinessDays(this DateTime date, int addDays) { while (addDays != 0) { date = date.AddDays(Math.Sign(addDays)); if (MyClass.IsBusinessDay(date)) { addDays = addDays - Math.Sign(addDays); } } return date; } } 

它使用这种方法,我认为将是有用的使用其他地方…

 public class MyClass { public static bool IsBusinessDay(DateTime date) { switch (date.DayOfWeek) { case DayOfWeek.Monday: case DayOfWeek.Tuesday: case DayOfWeek.Wednesday: case DayOfWeek.Thursday: case DayOfWeek.Friday: return true; default: return false; } } } 

如果你不想打扰你可以用if ((date.DayOfWeek != DayOfWeek.Saturday) && (date.DayOfWeek != DayOfWeek.Sunday))取代if (MyClass.IsBusinessDay(date)) if ((date.DayOfWeek != DayOfWeek.Saturday) && (date.DayOfWeek != DayOfWeek.Sunday))

所以,现在你可以做

 var myDate = DateTime.Now.AddBusinessDays(-3); 

要么

 var myDate = DateTime.Now.AddBusinessDays(5); 

以下是一些testing的结果:

testing预期结果
星期四星期四-4个工作日
星期三星期五-3个工作日
周一+3个工作日星期一
星期三星期三-7个工作日
星期二星期二-5个工作日星期二
周一周一+1个工作日
星期一星期一+1个工作日
星期五星期五-1个工作日
周一周五周五-1工作日
周一周二周一+1个工作日
周一周一+0个工作日周一

随着国际化,这是困难的。 正如特会上的其他议题所提到的,假期当然不同,甚至从省到省也不尽相同。 大多数政府不会安排五天以上的假期。

 public static DateTime AddBusinessDays(this DateTime date, int days) { date = date.AddDays((days / 5) * 7); int remainder = days % 5; switch (date.DayOfWeek) { case DayOfWeek.Tuesday: if (remainder > 3) date = date.AddDays(2); break; case DayOfWeek.Wednesday: if (remainder > 2) date = date.AddDays(2); break; case DayOfWeek.Thursday: if (remainder > 1) date = date.AddDays(2); break; case DayOfWeek.Friday: if (remainder > 0) date = date.AddDays(2); break; case DayOfWeek.Saturday: if (days > 0) date = date.AddDays((remainder == 0) ? 2 : 1); break; case DayOfWeek.Sunday: if (days > 0) date = date.AddDays((remainder == 0) ? 1 : 0); break; default: // monday break; } return date.AddDays(remainder); } 

我迟到了,但是我做了一个小型的图书馆,在工作日里做了简单的操作所需的所有定制工作……我把它留在这里: 工作日pipe理

  public static DateTime AddBusinessDays(DateTime date, int days) { if (days == 0) return date; int i = 0; while (i < days) { if (!(date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)) i++; date = date.AddDays(1); } return date; } 

我想要一个支持负数天的“AddBusinessDays”来添加,而我最终得到这个:

 // 0 == Monday, 6 == Sunday private static int epochDayToDayOfWeek0Based(long epochDay) { return (int)Math.floorMod(epochDay + 3, 7); } public static int daysBetween(long fromEpochDay, long toEpochDay) { // http://stackoverflow.com/questions/1617049/calculate-the-number-of-business-days-between-two-dates final int fromDOW = epochDayToDayOfWeek0Based(fromEpochDay); final int toDOW = epochDayToDayOfWeek0Based(toEpochDay); long calcBusinessDays = ((toEpochDay - fromEpochDay) * 5 + (toDOW - fromDOW) * 2) / 7; if (toDOW == 6) calcBusinessDays -= 1; if (fromDOW == 6) calcBusinessDays += 1; return (int)calcBusinessDays; } public static long addDays(long epochDay, int n) { // https://alecpojidaev.wordpress.com/2009/10/29/work-days-calculation-with-c/ // NB: in .NET, Sunday == 0, but in our code Monday == 0 final int dow = (epochDayToDayOfWeek0Based(epochDay) + 1) % 7; final int wds = n + (dow == 0 ? 1 : dow); // Adjusted number of working days to add, given that we now start from the immediately preceding Sunday final int wends = n < 0 ? ((wds - 5) / 5) * 2 : (wds / 5) * 2 - (wds % 5 == 0 ? 2 : 0); return epochDay - dow + // Find the immediately preceding Sunday wds + // Add computed working days wends; // Add weekends that occur within each complete working week } 

不需要循环,因此即使对于“大”添加也应该是相当快的。

它与从历元开始的许多日历date一起工作,因为这是由新的JDK8 LocalDate类公开的,并且我正在使用Java。 应该很简单,以适应其他设置。

基本属性是addDays总是返回一个工作日,而对于所有dndaysBetween(d, addDays(d, n)) == n

注意,从理论上讲,加0天和减0天应该是不同的操作(如果你的date是星期天,加0天应该带你到星期一,减去0天应该带你到星期五)。 由于不存在负数0(在浮点数之外!),所以我select解释一个n = 0的参数,意思是增加 0天。

我相信这可能是GetBusinessDays更简单的方法:

  public int GetBusinessDays(DateTime start, DateTime end, params DateTime[] bankHolidays) { int tld = (int)((end - start).TotalDays) + 1; //including end day int not_buss_day = 2 * (tld / 7); //Saturday and Sunday int rest = tld % 7; //rest. if (rest > 0) { int tmp = (int)start.DayOfWeek - 1 + rest; if (tmp == 6 || start.DayOfWeek == DayOfWeek.Sunday) not_buss_day++; else if (tmp > 6) not_buss_day += 2; } foreach (DateTime bankHoliday in bankHolidays) { DateTime bh = bankHoliday.Date; if (!(bh.DayOfWeek == DayOfWeek.Saturday || bh.DayOfWeek == DayOfWeek.Sunday) && (start <= bh && bh <= end)) { not_buss_day++; } } return tld - not_buss_day; } 

唯一真正的解决scheme是让这些调用访问定义您的业务日历的数据库表。 你可以在星期一到星期五的工作周期内编写代码,但是没有太多的困难,但是处理假期会是一个挑战。

编辑添加非优雅和未经testing的部分解决scheme:

 public static DateTime AddBusinessDays(this DateTime date, int days) { for (int index = 0; index < days; index++) { switch (date.DayOfWeek) { case DayOfWeek.Friday: date = date.AddDays(3); break; case DayOfWeek.Saturday: date = date.AddDays(2); break; default: date = date.AddDays(1); break; } } return date; } 

我也违反了无循环的要求。

这里是我的代码,出发date和客户交货date。

  // Calculate departure date TimeSpan DeliveryTime = new TimeSpan(14, 30, 0); TimeSpan now = DateTime.Now.TimeOfDay; DateTime dt = DateTime.Now; if (dt.TimeOfDay > DeliveryTime) dt = dt.AddDays(1); if (dt.DayOfWeek == DayOfWeek.Saturday) dt = dt.AddDays(1); if (dt.DayOfWeek == DayOfWeek.Sunday) dt = dt.AddDays(1); dt = dt.Date + DeliveryTime; string DepartureDay = "today at "+dt.ToString("HH:mm"); if (dt.Day!=DateTime.Now.Day) { DepartureDay = dt.ToString("dddd at HH:mm", new CultureInfo(WebContextState.CurrentUICulture)); } Return DepartureDay; // Caclulate delivery date dt = dt.AddDays(1); if (dt.DayOfWeek == DayOfWeek.Saturday) dt = dt.AddDays(1); if (dt.DayOfWeek == DayOfWeek.Sunday) dt = dt.AddDays(1); string DeliveryDay = dt.ToString("dddd", new CultureInfo(WebContextState.CurrentUICulture)); return DeliveryDay; 

快乐的编码。

 public static DateTime AddWorkingDays(this DateTime date, int daysToAdd) { while (daysToAdd > 0) { date = date.AddDays(1); if (date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday) { daysToAdd -= 1; } } return date; } 

希望这有助于某人。

 private DateTime AddWorkingDays(DateTime addToDate, int numberofDays) { addToDate= addToDate.AddDays(numberofDays); while (addToDate.DayOfWeek == DayOfWeek.Saturday || addToDate.DayOfWeek == DayOfWeek.Sunday) { addToDate= addToDate.AddDays(1); } return addToDate; }