我有场景用户会输入开始日期和结束日期。我在该日期范围之间列出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
};
答案 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();
}
从当前日期返回一周的第二天,可以这样使用:
DateTime comingSunday = DateTime.Now.NextDayOfWeek(DayOfWeek.Sunday);
这个是本周的前一天:
这从当前日期开始返回前一天,可以这样使用:
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年