生成以下工作周的日期列表

时间:2016-04-25 03:34:29

标签: c# .net

我正在尝试根据以下条件生成日期列表:

  • 如果今天是星期三和下午6:00之后,则是星期三之后,然后生成下一个工作周。

  • 否则生成当前工作周。

工作周定义为周一至周五。

到目前为止,谷歌搜索并从这里拉出两个答案,我有这个扩展,它给了我基于当天的下一个指定日期:

public static DateTime Next(this DateTime dt, DayOfWeek startoOfWeek)
{
    var start = (int)dt.DayOfWeek;
    var target = (int)startoOfWeek;
    if (target <= start)
    {
        target += 7;
    }
     return dt.AddDays(target - start);
}

来自:How to get the date of the next Sunday?

我还有以下工作日:

var daysOfWeek = Enum.GetValues(typeof(DayOfWeek))
            .OfType<DayOfWeek>()
            .Skip(1)
            .TakeWhile(day => day != DayOfWeek.Saturday)
            .ToList();

我继续测试它:

foreach (var day in daysOfWeek)
{
    Debug.WriteLine(DateTime.Now.Next(day).Date.ToString(CultureInfo.CurrentCulture));
}

由于今天是2016年4月24日星期日,我得到下周的正确输出:

> 4/25/2016 0:00:00
> 4/26/2016 0:00:00
> 4/27/2016 0:00:00
> 4/28/2016 0:00:00
> 4/29/2016 0:00:00

但如果今天在2016年4月27日星期三说,那么我得到:

> 5/2/2016 0:00:00
> 5/3/2016 0:00:00
> 5/4/2016 0:00:00
> 4/28/2016 0:00:00
> 4/29/2016 0:00:00

我越来越近了,但我想知道是否有一种比我已经做过的更简单的方法,或者是否已经有答案了。

2 个答案:

答案 0 :(得分:0)

这看起来有点矫枉过正,但我​​会把它分解成小功能。首先,对于任何日期,给定一周中的某一天,该工作日的前一个实例是什么,包括当前日期? (翻译 - 给出一个日期,上一个星期一的日期是什么,包括星期一的日期?)

然后,对于任何给定日期和天数,日期范围是什么?

public static class DateFunctions
{
    public static DateTime GetPreviousInstanceOfWeekDay(DateTime forDate, 
        DayOfWeek dayOfWeek)
    {
        return forDate.DayOfWeek >= dayOfWeek 
            ? forDate.AddDays(dayOfWeek - forDate.DayOfWeek).Date 
            : forDate.AddDays(-(7-(dayOfWeek - forDate.DayOfWeek))).Date;
    }

    public static IEnumerable<DateTime> GetDateRange(DateTime startDate, int length)
    {
        return Enumerable.Range(0, length - 1).Select(x => startDate.Date.AddDays(x));
    }
}

主要原因是这是我在第一次尝试时没有想到的那种东西,最简单的验证方法是进行一些单元测试。

[TestMethod]
public void ReturnsPreviousMondayForGivenThursday()
{
    var monday = DateFunctions.GetPreviousInstanceOfWeekDay(DateTime.Parse("4/21/2016"), 
        DayOfWeek.Monday);
    Assert.AreEqual(DateTime.Parse("4/18/2016"), monday);
}

[TestMethod]
public void ReturnsPreviousSaturdayForGivenSunday()
{
    var saturday = DateFunctions.GetPreviousInstanceOfWeekDay(DateTime.Parse("4/17/2016"), 
        DayOfWeek.Saturday);
    Assert.AreEqual(DateTime.Parse("4/16/2016"), saturday);
}

[TestMethod]
public void ReturnsSundayForGivenSunday()
{
    var sunday = DateFunctions.GetPreviousInstanceOfWeekDay(DateTime.Parse("4/24/2016"), 
        DayOfWeek.Sunday);
    Assert.AreEqual(DateTime.Parse("4/24/2016"), sunday);
}

这也使周三/下午6点的支票与其他支票分开。这个函数只是结合了其他函数,它引入的唯一新东西是逻辑来检查它是否应该从上周一或下周一开始返回五天。 (我甚至可以将它放在一个单独的函数中。一些额外的代码行和一个或两个单元测试非常适合安心。)

public static IEnumerable<DateTime> GetWeekDaysForCurrentOrNextWeek(DateTime forDate)
{
    //Badly named variable. It's late.
    var getStartForWeek = forDate.AddHours(6).DayOfWeek > DayOfWeek.Wednesday
        ? forDate.AddDays(7) : forDate;
    return
        DateFunctions.GetDateRange(
        GetPreviousInstanceOfWeekDay(getStartForWeek, DayOfWeek.Monday), 5);
}

答案 1 :(得分:0)

这对我有用:

public static DateTime GetStartOfWorkWeek(this DateTime now)
{
    var monday = now.AddDays(1 - (int)now.DayOfWeek).Date;
    if (now.Subtract(monday).TotalHours >= 66.0)
    // 66.0 hours from Midnight Mon to 6pm Wed
    {
        monday = monday.AddDays(7.0);
    }
    return monday;
}

如果我运行此代码:

var now1 = new DateTime(2016, 4, 27, 17, 59, 0);
var now2 = new DateTime(2016, 4, 27, 18, 0, 0);

var monday1 = now1.GetStartOfWorkWeek();
var monday2 = now2.GetStartOfWorkWeek();

......我得到了这些价值观:

now1
2016/04/27 17:59 Wednesday 

monday1
2016/04/25 00:00 Monday 

now2
2016/04/27 18:00 Wednesday 

monday2
2016/05/02 00:00 Monday