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); }
第二个函数GetBusinessDays可以实现如下:
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
总是返回一个工作日,而对于所有d
和n
, daysBetween(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; }