【问题标题】:Get Every Week's Start and End Date from List<DateTime> using LINQ使用 LINQ 从 List<DateTime> 获取每周的开始和结束日期
【发布时间】:2015-01-28 11:47:08
【问题描述】:

我有场景用户将输入开始日期结束日期。我列出了该日期范围之间的DateTime

现在我有DateTime 的列表,假设从本月 1 日到本月 30 日,我想在结果集中获取每周的开始和结束日期,例如:

WeekStartDate   WeekEndDate  
01/01/2015      04/01/2015
05/01/2015      11/01/2015

我已经尝试使用 linq 来获得所需的结果,但我无法获得所需的输出,这是我的尝试:

var dating = from d in dates
             group d by new { d.Day, d.DayOfWeek,d.Date } into g
             where g.Key.DayOfWeek == DayOfWeek.Monday || g.Key.DayOfWeek == DayOfWeek.Sunday
             select g;

编辑:

我现在能够获得周组合,但它没有完成,因为它错过了周一检查的第一周,因为第一个日期可能不是周一:

var dating = from d in dates
             let NextWeekDate = d.Date.AddDays(6)
             group d by new { d.Day, d.DayOfWeek, d.Date, NextWeekDate } into g
             where g.Key.DayOfWeek == DayOfWeek.Monday
             select new { 
                          StartWeekDate = g.Key.Date, 
                          EndWeekDate = g.Key.NextWeekDate 
                        };

【问题讨论】:

  • 如果我错了,请纠正我 - 您希望结果包含 1. 本月的第一个日期 2. 所有星期日结束时间 3. 所有星期一开始时间。我说的对吗?
  • @MotiAzu 我想他希望每个星期的开始和结束日期都是一对。所以结果应该是这些对的列表。
  • @Selman22 我认为你是对的,有道理。
  • @Selman22 你没看错,我需要给定日期范围内每周的开始和结束日期
  • 21k 你应该知道这个网站是如何工作的。将您的解决方案作为答案,而不是编辑到问题中,并且不要将[Solved] 编辑到您的标题中。

标签: c# linq datetime


【解决方案1】:

我在某处找到了这两种扩展方法,它们帮助我获得了所需的输出:

public static DateTime NextDayOfWeek(this DateTime dt, DayOfWeek dayOfWeek)
{
     int offsetDays = dayOfWeek - dt.DayOfWeek;
     return dt.AddDays(offsetDays > 0 ? offsetDays : offsetDays + 7).AtMidnight();
}

NextDayOfWeek():

从当前日期返回一周的第二天,可以这样使用:

DateTime comingSunday = DateTime.Now.NextDayOfWeek(DayOfWeek.Sunday);

这个是为了获取本周的前一天:

PreviousDayOfWeek():

从当前日期返回一周的前一天,可以这样使用:

public static DateTime PreviousOfWeek(this DateTime dt, DayOfWeek dayOfWeek)
{
   int offsetDays = -(dt.DayOfWeek - dayOfWeek);
   return dt.AddDays(offsetDays).AtMidnight();
}

它可以像这样使用:

DateTime thisWeekMonday = DateTime.Now.PreviousDayOfWeek(DayOfWeek.Monday);

这是我的杂乱查询,我重构并发现不需要分组:

var dating = from d in dates
             let PreviousDate = d.PreviousOfWeek(DayOfWeek.Monday)
             let NextWeekDate = d.NextDayOfWeek(DayOfWeek.Sunday)
             group d by new 
                       { 
                         d.Day, 
                         d.DayOfWeek, 
                         d.Date, 
                         NextWeekDate 
                       } into g
             where g.Key.DayOfWeek == DayOfWeek.Monday
             select new 
                   { 
                     StartWeekDate = g.Key.DayOfWeek != DayOfWeek.Monday ? g.Key.Date.PreviousOfWeek(DayOfWeek.Monday) : g.Key.Date, 
                      EndWeekDate = g.Key.NextWeekDate 
                   };

重构一:

var dating22 = (from d in dates
               where d.DayOfWeek == DayOfWeek.Monday
               select new 
               { 
                 StartWeekDate = d.DayOfWeek != DayOfWeek.Monday ? d.Date.PreviousOfWeek(DayOfWeek.Monday) : d.Date, 
                 EndWeekDate = d.NextDayOfWeek(DayOfWeek.Sunday) 
               }).Distinct();

如果我们想从开始日期传递到以后:

DateTime startDate = new DateTime(2015, 1, 28);
DateTime endDate = new DateTime(2015, 2, 10);

var dates = startDate.Range(endDate);

var fromStartDateToEndDate = )from d in dates
                             where d.DayOfWeek == DayOfWeek.Monday
                             select new 
                                   { 
                                      StartWeekDate = d.Date, 
                                      EndWeekDate = d.Date.NextDayOfWeek(DayOfWeek.Sunday) 
                                   }).Distinct();

如果我们希望它从开始日期的星期一开始,因为开始日期可以不是星期一,所以我们需要从星期一开始,如果这样:

var fromStartingWeekOfStartDateRefactored = (from d in dates
                                            where d.DayOfWeek == DayOfWeek.Monday
                                            select new 
                                                 { 
                                                   StartWeekDate = d.DayOfWeek != DayOfWeek.Monday ? d.Date.PreviousOfWeek(DayOfWeek.Monday) : d.Date, 
                                                   EndWeekDate = d.NextDayOfWeek(DayOfWeek.Sunday) 
                                                  }).Distinct();

【讨论】:

    【解决方案2】:

    这应该可以解决问题。代码是不言自明的;我用了Tuple&lt;&gt;作为一周的代表。

    var startDate = DateTime.Now.AddDays(-26);
    var endDate = DateTime.Now.AddDays(1);
    
    var weeks = new List<Tuple<DateTime, DateTime>>();
    for (var date = startDate; date <= endDate; date = date.AddDays(1))
    {
        if (date == startDate)
        {
            // find the next Sunday 
            var start = (int)date.DayOfWeek;
            var target = (int)DayOfWeek.Sunday;
            if (target < start)
                target += 7;
            weeks.Add(Tuple.Create(date, date.AddDays(target - start)));
        }
        else if (date.DayOfWeek == DayOfWeek.Monday)
        {
            weeks.Add(Tuple.Create(date, date.AddDays(6)));
        }
    }
    

    请注意,如果第一个日期是星期天(例如 2015 年 1 月 4 日),则第一周从那天开始并结束。

    【讨论】:

      【解决方案3】:

      如果我正确理解了您的问题,您有一个日期集合,这些日期从一个月的某个可变点开始,并且您想要一个星期开始和结束的列表。 @Selman22 是在正确的轨道上,但你不能在 1 月 1 日加上 6 天来获得下一个星期天。 这很相似,但会正确处理第一周的情况:

      int firstDay = dates.Min(x => x).Day;
      var dating = from d in dates
                   where d.DayOfWeek == DayOfWeek.Monday || d.Day == firstDay
                      select new
                      {
                          StartDate = d,
                          EndDate = d.AddDays(
                              Enumerable.Range(0, 7)
                                        .First(n => d.AddDays(n).DayOfWeek == DayOfWeek.Sunday))
                      };
      

      【讨论】:

        【解决方案4】:
        /// <summary>
        /// Customized class for the Date Range Container...
        /// </summary>
        [DataContract]
        public class WeekRange
        {
            [DataMember]
            public string Range { get; set; }
            [DataMember]
            public string StartDate { get; set; }
            [DataMember]
            public string EndDate { get; set; }
            [DataMember]
            public int Week { get; set; }
            [DataMember]
            public int Month { get; set; }
            [DataMember]
            public int Year { get; set; }
        }
        
        
        
        
                 /// <summary>
                /// Get the Week Range for the Given Date Range.....
                /// </summary>
                /// <param name="startDate"></param>
                /// <param name="endDate"></param>
                /// <returns></returns>
                public static List<WeekRange> WeekDays(DateTime startDate, DateTime endDate)
                {
                    DateTime startDateToCheck = startDate;
                    DateTime dateToCheck = startDate;
                    DateTime dateRangeBegin = dateToCheck;
                    DateTime dateRangeEnd = endDate;
        
                    List<WeekRange> weekRangeList = new List<WeekRange>();
                    WeekRange weekRange = new WeekRange();
        
                    while ((startDateToCheck.Year <= endDate.Year) && (startDateToCheck.Month <= endDate.Month) && dateToCheck <= endDate)
                    {
                        int week = 0;
        
                        while (startDateToCheck.Month == dateToCheck.Month && dateToCheck <= endDate)
                        {
                            week = week + 1;
                            dateRangeBegin = dateToCheck.AddDays(-(int)dateToCheck.DayOfWeek);
                            dateRangeEnd = dateToCheck.AddDays(6 - (int)dateToCheck.DayOfWeek);
        
                            if ((dateRangeBegin.Date < dateToCheck) && (dateRangeBegin.Date.Month != dateToCheck.Month))
                            {
                                dateRangeBegin = new DateTime(dateToCheck.Year, dateToCheck.Month, dateToCheck.Day);
                            }
        
                            if ((dateRangeEnd.Date > dateToCheck) && (dateRangeEnd.Date.Month != dateToCheck.Month))
                            {
                                DateTime dtTo = new DateTime(dateToCheck.Year, dateToCheck.Month, 1);
                                dtTo = dtTo.AddMonths(1);
                                dateRangeEnd = dtTo.AddDays(-(dtTo.Day));
                            }
                            if (dateRangeEnd.Date > endDate)
                            {
                                dateRangeEnd = new DateTime(dateRangeEnd.Year, dateRangeEnd.Month, endDate.Day);
                            }
                            weekRange = new WeekRange
                            {
                                StartDate = dateRangeBegin.ToShortDateString(),
                                EndDate = dateRangeEnd.ToShortDateString(),
                                Range = dateRangeBegin.Date.ToShortDateString() + '-' + dateRangeEnd.Date.ToShortDateString(),
                                Month = dateToCheck.Month,
                                Year = dateToCheck.Year,
                                Week = week
                            };
                            weekRangeList.Add(weekRange);
                            dateToCheck = dateRangeEnd.AddDays(1);
                        }
                        startDateToCheck = startDateToCheck.AddMonths(1);
                    }
                    return weekRangeList;
                }
        

        代码接受输入 (Year,Month):假设是 (2014,08) Aug-2014。现在运行代码,我们将周范围值添加到周范围对象。

        输出将显示为日期列表,其中一个示例值如下所示:-

        结束日期:- 08/02/2014 月 :- 8 范围:- 08/01/2014-08/02/2014 开始日期:- 08/01/2014 周:- 1 年份:- 2014

        【讨论】:

        • 为你的答案添加一些解释。?
        • 上面的代码将以星期的形式给出结果集,其中嵌入了日期范围。希望它有所帮助.... :)
        • 不是发表评论,而是编辑你的答案,然后添加解释?
        猜你喜欢
        • 1970-01-01
        • 2010-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-05
        • 1970-01-01
        相关资源
        最近更新 更多