获取两个日期的工作日范围

时间:2015-03-20 08:45:40

标签: c# sql asp.net linq linq-to-sql

我在SQL中有一个UDF表函数,其功能如下

select * from dbo.GetWeekdayRange(convert(datetime, '11/03/2015', 103), convert(datetime, '31/03/2015', 103))

输出:

WeekStartDate              WeekEndDate
-------------------------------------------------
2015-03-11 00:00:00.000   2015-03-15 00:00:00.000
2015-03-16 00:00:00.000   2015-03-22 00:00:00.000
2015-03-23 00:00:00.000   2015-03-29 00:00:00.000
2015-03-30 00:00:00.000   2015-03-31 00:00:00.000

C#中是否有这样的功能?我也尝试使用LINQ,但无法成功。我试着搜索它,但我找不到它们。

1 个答案:

答案 0 :(得分:3)

这可以很容易地在C#中复制,我确信有一个更有效的解决方案,但这有效:

public static IEnumerable<DateRange> GetWeekdayRange(DateTime startDate, DateTime endDate, DayOfWeek weekEndsOn = DayOfWeek.Sunday)
{
    var currStartDate = startDate;
    var currDate = startDate;
    while(currDate<endDate)
    {
        while(currDate.DayOfWeek != weekEndsOn && currDate<endDate)
        {
            currDate = currDate.AddDays(1);
        }
        yield return new DateRange{ WeekStartDate = currStartDate,WeekEndDate = currDate};
        currStartDate = currDate.AddDays(1);
        currDate = currStartDate;
    }
}

public struct DateRange
{
    public DateTime WeekStartDate{get;set;}
    public DateTime WeekEndDate{get;set;}
}

测试代码

var start = new DateTime(2015,3,11);
var end = new DateTime(2015,3,31);

var range = GetWeekdayRange(start,end);
foreach(var val in range)
{
    Console.WriteLine("{0:yyyy-MM-dd} - {1:yyyy-MM-dd}",val.WeekStartDate,val.WeekEndDate);
}

输出:

  

2015-03-11 - 2015-03-15
  2015-03-16 - 2015-03-22
  2015-03-23 - 2015-03-29
  2015-03-30 - 2015-03-31

实例:http://rextester.com/DGSX37215

如果你真的想要更多的LINQ-ey解决方案,你可以这样做 - 我发现它更难以阅读和理解正在发生的事情,但它提供了相同的输出。它使用日历将日期列表分组为几周,然后从组中选择MinMax

public static IEnumerable<DateRange> GetWeekdayRange(DateTime startDate, DateTime endDate, DayOfWeek weekStartsOn = DayOfWeek.Monday)
{
    var diff = endDate.Subtract(startDate).Days;
    var cal = System.Globalization.DateTimeFormatInfo.CurrentInfo.Calendar;
    var range = Enumerable.Range(0,diff+1).Select(v => startDate.AddDays(v))
                        .Select(d => new {Date=d, WeekNumber=cal.GetWeekOfYear(d, System.Globalization.CalendarWeekRule.FirstDay, weekStartsOn) })
                        .GroupBy(g => g.WeekNumber);

    return range.Select(g => new DateRange{WeekStartDate=g.Min(v => v.Date), WeekEndDate= g.Max(v => v.Date)});
}

实例:http://rextester.com/CXSXC66880