我想编写以下函数,将n
个工作日添加到DateTime
。但是,我希望工作日可配置:
public DateTime AddBusinessDays(DateTime dateTime, int n, IEnumerable<DayOfWeek> businessDays)
{
// ?
}
e.g。星期三可能是假期,所以我只想跳过那一天:
DateTime.Today.AddBusinessDays(
7,
new DayOfWeek[]
{
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday,
DayOfWeek.Sunday,
});
我意识到我可以编写一个天真的实现来查看每一天,但我正在寻找更好的实现。
到目前为止还没有工作示例,这里有一些xUnit测试来帮助测试不同的场景:
[Theory]
// Zero Values
[InlineData("01/01/2016", 0, "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday", "01/01/2016")]
[InlineData("01/01/2016", 0, "Saturday", "01/01/2016")]
// Positive Days
[InlineData("01/01/2016", 1, "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday", "02/01/2016")]
[InlineData("01/01/2016", 30, "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday", "31/01/2016")]
[InlineData("01/01/2016", 1, "Saturday", "02/01/2016")]
[InlineData("01/01/2016", 2, "Saturday", "09/01/2016")]
[InlineData("01/01/2016", 3, "Saturday", "16/01/2016")]
[InlineData("01/01/2016", 7, "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", "08/01/2016")]
// Negative Days
[InlineData("01/01/2016", -1, "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday", "31/12/2015")]
[InlineData("01/01/2016", -31, "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday", "01/12/2015")]
[InlineData("01/01/2016", -1, "Saturday", "26/12/2015")]
[InlineData("01/01/2016", -2, "Saturday", "19/12/2015")]
[InlineData("01/01/2016", -3, "Saturday", "12/12/2015")]
public void AddBusinessDays(string start, int days, string businessDays, string expectedEnd)
{
var daysOfWeek = businessDays.Split(',').Select(x => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), x));
var actualEnd = DateTime.Parse(start).AddBusinessDays(days, daysOfWeek);
Assert.Equal(DateTime.Parse(expectedEnd), actualEnd);
}
答案 0 :(得分:2)
这应该这样做。它使用保留计数器的天数,并且仅在将已配置的工作日添加到日期时将其减少。根据{{3}}的建议,我使用了HashSet来加快查找速度。然而,它仍然是一种非常线性的缩放算法。
public DateTime AddBusinessDays(DateTime dateTime, int n, IEnumerable<DayOfWeek> businessDays)
{
var tmpDate = dateTime;
var bdLookup = new HashSet<DayOfWeek>(businessDays);
while (n > 0)
{
tmpDate = tmpDate.AddDays(1);
if (bdLookup.Contains(tmpDate.DayOfWeek))
n--;
}
return tmpDate;
}
答案 1 :(得分:2)
J. Steen’s answer的恒定时间变化:
public DateTime AddBusinessDays(DateTime date, int n, IEnumerable<DayOfWeek> businessDays)
{
var days = new HashSet<DayOfWeek>(businessDays);
// add full weeks
date = date.AddDays(7 * n / days.Count);
// get the remainder
n %= days.Count;
// add the remaining days; at most 6 times
while (n > 0)
{
date = date.AddDays(1);
if (days.Contains(date.DayOfWeek))
n--;
}
return date;
}