将工作日添加到可配置工作日的日期时间

时间:2016-07-29 10:58:00

标签: c# .net datetime dayofweek

我想编写以下函数,将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);
}

2 个答案:

答案 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;
}