给出日期和假期列表,如何将给定的工作日数添加到此日期?对于较小的问题有很多解决方案,没有考虑到假期(例如参见Adding Days to a Date but Excluding Weekends)。
编辑:我正在寻找O(1)或至少线性(假日数量)解决方案。
请帮忙 谢谢 康斯坦丁
答案 0 :(得分:1)
接近O(1)(没有初始时间)
如果你真的想要一个O(1)解决方案,我希望你不要考虑初始化的问题。
初始化:
初始化代码,只需要一次,然后缓存结果。
查询/计算
List<DateTime> validWorkdays = // ;
Dictionary<DateTime, int> lookupIndexOfValidWorkday = // ;
DateTime AddWorkdays(DateTime start, int count) {
var startIndex = lookupIndexOfValidWorkday[start];
return validWorkDays[startIndex + count];
}
Concerning the retrieve from the dictionary:
获取或设置此属性的值接近O(1)操作。
O(n)假期数
假设假期列表从最旧到最新排序。 (Credits for weekdays formula)
DateTime AddBusinessDay(DateTime start, int count, IEnumerable<DateTime> holidays) {
int daysToAdd = count + ((count/ 5) * 2) + ((((int)start.DayOfWeek + (count % 5)) >= 5) ? 2 : 0);
var end = start.AddDays(daysToAdd);
foreach(var dt in holidays) {
if (dt >= start && dt <= end) {
end = end.AddDays(1);
if (end.DayOfWeek == DayOfWeek.Saterday) {
end = end.AddDays(2);
}
}
}
return end;
}
可以优化此方法。
创建一个只计算结果的简单公式非常困难,就像您链接的问题中的答案一样。因为当您调整假期时,您需要考虑可能属于您的范围的新假期。对于周末,您知道它们之间存在固定的间隔。
答案 1 :(得分:0)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace DateThing
{
class Program
{
static void Main(string[] args)
{
var holidays = new List<DateTime>()
{
new DateTime(2010, 12, 25),
new DateTime(2010, 12, 26)
};
var futureDate = CalculateFutureDate(DateTime.Today, 20, holidays);
}
static DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays, ICollection<DateTime> holidays)
{
var futureDate = fromDate;
for (var i = 0; i < numberofWorkDays; i++ )
{
if (futureDate.DayOfWeek == DayOfWeek.Saturday || futureDate.DayOfWeek == DayOfWeek.Sunday ||
(holidays != null && holidays.Contains(futureDate)))
futureDate = futureDate.AddDays(1); // Increase FutureDate by one because of condition
futureDate = futureDate.AddDays(1); // Add a working day
}
return futureDate;
}
}
}
答案 2 :(得分:0)
试试这个......
private DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays, ICollection<DateTime> holidays)
{
var futureDate = fromDate;
var daterange = Enumerable.Range(1, numberofWorkDays * 2);
var dateSet = daterange.Select (d => futureDate.AddDays(d));
var dateSetElim = dateSet.Except(holidays).Except(dateSet.Where( s =>s.DayOfWeek == DayOfWeek.Sunday).Except(dateSet.Where (s=>s.DayOfWeek==DayOfWeek.Saturday) ));
//zero-based array
futureDate = dateSetElim.ElementAt(numberofWorkDays-1);
return futureDate;
}
答案 3 :(得分:0)
//下面的代码正常工作......如果您有任何疑虑,请告诉我
DateTime AddBusinessDays(int noofDays, DateTime dtCurrent)
{
var holidays = new List<DateTime>() { new DateTime(2013, 10, 22), new DateTime(2013, 10, 28)};
DateTime tempdt = new DateTime(dtCurrent.Year, dtCurrent.Month, dtCurrent.Day);
// if starting day is non working day adjust to next working day
tempdt = ExcludeNotWorkingDay(tempdt, holidays);
// if starting day is non working day adjust to next working day then minus 1 day in noofadding days
if (tempdt.Date > dtCurrent.Date && !(noofDays == 0))
noofDays = noofDays - 1;
while (noofDays > 0)
{
tempdt = tempdt.AddDays(1);
// if day is non working day adjust to next working day
tempdt = ExcludeNotWorkingDay(tempdt, holidays);
noofDays = noofDays - 1;
}
return tempdt;
}
DateTime ExcludeNotWorkingDay(DateTime dtCurrent, List<DateTime> holidays)
{
while (!IsWorkDay(dtCurrent, holidays))
{
dtCurrent = dtCurrent.AddDays(1);
}
return dtCurrent;
}
bool IsWorkDay(DateTime dtCurrent, List<DateTime> holidays)
{
if ((dtCurrent.DayOfWeek == DayOfWeek.Saturday || dtCurrent.DayOfWeek == DayOfWeek.Sunday ||
holidays.Contains(dtCurrent)))
{
return false;
}
else
{
return true;
}
}
答案 4 :(得分:-1)
这样的事可能
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DateThing
{
class Program
{
static void Main(string[] args)
{
var holidays = new List<DateTime>()
{
new DateTime(2010, 12, 25),
new DateTime(2010, 12, 26)
};
var workDays = GetNumberOfWorkDays(DateTime.Today, new DateTime(2011, 1, 1), holidays);
}
static int GetNumberOfWorkDays(DateTime fromDate, DateTime toDate, ICollection<DateTime> holidays)
{
var days = 0;
for (var i = fromDate; i < toDate; )
{
if (i.DayOfWeek != DayOfWeek.Saturday && i.DayOfWeek != DayOfWeek.Sunday &&
(holidays != null && !holidays.Contains(i)))
days++;
i = i.AddDays(1);
}
return days;
}
}
}