【问题标题】:Get weekday range from two dates从两个日期获取工作日范围
【发布时间】:2015-03-20 08:45:40
【问题描述】:

我在 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,但未能成功。我试图搜索它,但我没有找到任何一个。

【问题讨论】:

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


    【解决方案1】:

    这可以很容易地在 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 的解决方案,您可以这样做 - 我发现它更难阅读和理解正在发生的事情,但它提供了相同的输出。它使用日历将日期列表分组为周,然后从组中选择Min 和Max

    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

    【讨论】:

    • 你的输出是错误的 11-15 16-22 23-29 .. 周末在哪里?
    • @RameshRajendran - 再看看这个问题 - 它有点误导,但 OP 的输出有周六和周日。他正在寻找星期开始日期(星期一)和星期结束日期(星期日)
    • 非常感谢伙计,效果很好。但是,您能详细说明一下高效解决方案是什么意思吗?
    • 双嵌套while 循环通常不是特别有效的解决方案。一些天才可能会想出如何更快地做到这一点,但老实说,只要你没有在一个紧密的循环中调用这个方法 50,000 次,我就不会太担心。
    • 不,我修改了返回列表的方法,我只调用了一次该方法,然后修改了输出列表。非常感谢您的宝贵时间。
    猜你喜欢
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2019-08-25
    相关资源
    最近更新 更多