C# 将工作日添加到可配置工作日的DateTime

C# 将工作日添加到可配置工作日的DateTime,c#,.net,datetime,dayofweek,C#,.net,Datetime,Dayofweek,我想编写以下函数,将n工作日数添加到DateTime。但是,我希望工作日是可配置的: public DateTime AddBusinessDays(DateTime dateTime, int n, IEnumerable<DayOfWeek> businessDays) { // ? } 我意识到我可以编写一个简单的实现来每天查看,但我正在寻找一个更好的实现 更新 到目前为止还没有工作示例,以下是一些xUnit测试来帮助测试不同的场景: [Theory] // Zero

我想编写以下函数,将
n
工作日数添加到
DateTime
。但是,我希望工作日是可配置的:

public DateTime AddBusinessDays(DateTime dateTime, int n, IEnumerable<DayOfWeek> businessDays)
{
    // ?
}
我意识到我可以编写一个简单的实现来每天查看,但我正在寻找一个更好的实现

更新 到目前为止还没有工作示例,以下是一些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);
}

这应该可以做到。它使用天数保留计数器,并且仅在将已配置的工作日添加到日期时递减计数器。根据来自的建议,我使用了哈希集来加快查找速度。然而,它仍然是一个非常线性的缩放算法

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;
}
public DateTime AddBusinessDays(DateTime DateTime,int n,IEnumerable businessDays)
{
var tmpDate=日期时间;
var bdLookup=新哈希集(businessDays);
而(n>0)
{
tmpDate=tmpDate.AddDays(1);
if(bdLookup.Contains(tmpDate.DayOfWeek))
n--;
}
返回tmpDate;
}

这应该可以。它使用天数保留计数器,并且仅在将已配置的工作日添加到日期时递减计数器。根据来自的建议,我使用了哈希集来加快查找速度。然而,它仍然是一个非常线性的缩放算法

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;
}
public DateTime AddBusinessDays(DateTime DateTime,int n,IEnumerable businessDays)
{
var tmpDate=日期时间;
var bdLookup=新哈希集(businessDays);
而(n>0)
{
tmpDate=tmpDate.AddDays(1);
if(bdLookup.Contains(tmpDate.DayOfWeek))
n--;
}
返回tmpDate;
}

恒定时间变化:

public DateTime AddBusinessDays(DateTime日期,int n,IEnumerable businessDays)
{
var天数=新哈希集(businessDays);
//添加完整周数
日期=date.AddDays(7*n/天.计数);
//得到剩余的
n%=天数。计数;
//添加剩余天数;最多6次
而(n>0)
{
日期=日期。添加天数(1);
if(天包含(星期日))
n--;
}
返回日期;
}

恒定时间变化:

public DateTime AddBusinessDays(DateTime日期,int n,IEnumerable businessDays)
{
var天数=新哈希集(businessDays);
//添加完整周数
日期=date.AddDays(7*n/天.计数);
//得到剩余的
n%=天数。计数;
//添加剩余天数;最多6次
而(n>0)
{
日期=日期。添加天数(1);
if(天包含(星期日))
n--;
}
返回日期;
}


你最好把一周中的几天放到某种形式的散列集中,这样你就不会迭代所有的元素——毕竟有人可能会在一个日期上增加10000天,这会让Slooowi感到失望。我刚刚测试了增加10000天,它在8毫秒内完成了测试。所以这相当慢只需两行更改
var bdLookup=newhashset(businessDays)
bdLookup.Contains(tmpDate.DayOfWeek)
很好的建议,谢谢。我添加了它。在10000天时仍以4ms的速度减慢。增加50年的工作日大约需要1毫秒。但是如果有人提前那么长时间预约,他们应该得到所需的时间@J.Steen既然你已经在做基准测试了,你能看看我对你答案的修改吗?它是固定时间的,所以它应该更快:)你最好把一周中的几天放到某种形式的HashSet中,这样你就不会迭代所有的元素——毕竟有人可能会在一个日期中增加10000天,这会让Slooowi测试增加10000天,它用了8毫秒。所以这相当慢只需两行更改
var bdLookup=newhashset(businessDays)
bdLookup.Contains(tmpDate.DayOfWeek)
很好的建议,谢谢。我添加了它。在10000天时仍以4ms的速度减慢。增加50年的工作日大约需要1毫秒。但是如果有人提前那么长时间预约,他们应该得到所需的时间@J.Steen既然你已经在做基准测试了,你能看看我对你答案的修改吗?时间是恒定的,所以速度应该更快:)哦,是的。快得多。我没有得到超过1ms的结果。直到几乎溢出日期时间。节省这些迭代非常好。=)加上400000个工作日,我得到的持续时间大约是00:00:00.00004。所以很小。哈哈:我想我们已经完成了这个问题的优化,如果天数为负呢?哦,是的。快得多。我没有得到超过1ms的结果。直到几乎溢出日期时间。节省这些迭代非常好。=)加上400000个工作日,我得到的持续时间大约是00:00:00.00004。所以哈哈,我想我们已经优化好这个问题了,如果天数为负呢?
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;
}