使用LINQ </datetime>从List <datetime>获取每周的开始和结束日期

时间:2015-01-28 11:47:09

标签: c# linq datetime

我有场景用户会输入开始日期结束日期。我在该日期范围之间列出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 
                        };

4 个答案:

答案 0 :(得分: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();

答案 1 :(得分:0)

这应该可以解决问题。代码不言自明;我用Tuple<>作为一周的代表。

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日),则第一周开始并在当天结束。

答案 2 :(得分:0)

如果我正确理解了您的问题,那么您有一个日期的集合,这些日期从一个月的变量点开始,您需要一个开始和周末的列表。 @ 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))
                };

答案 3 :(得分:-1)

/// <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;
        }

代码输入(年,月):让我们说(2014,08)2014年8月。现在运行代码,我们将周范围值添加到周范围对象。

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

EndDate: - 08/02/2014 月: - 8 范围: - 08/01 / 2014-08 / 02/2014 开课日期: - 2014年1月8日 周: - 1 年: - 2014年