我注意到原帖中的理想输出中有第1周、第2周等。这些不是一年中的周数,而是基于寄售日期显示的周的“索引”。在其他已提供答案的基础上,以下是我的解决方案:
void DoExample()
{
var range = new List<DateTime>();
var curDate = DateTime.ParseExact("07/12/2011", "dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture);
var maxDate = DateTime.ParseExact("22/12/2011", "dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture);
while(curDate < maxDate)
{
range.Add(curDate);
curDate = curDate.AddDays(1);
}
var c = GetConsignments(range, DayOfWeek.Sunday);
foreach(var v in c)
{
Console.WriteLine($"Week {v.EntryIndex + 1} (number {v.WeekOfYear} in year): (consignments between {v.RangeStart:dd/MM/yyyy} and {v.RangeEnd:dd/MM/yyyy}). Actual date range is {v.RangeStart:dd/MM/yyyy}-{v.RangeEnd:dd/MM/yyyy} ({(v.FullWeek ? "Full" : "Partial")} week)");
}
foreach (var v in c)
{
Console.WriteLine($"Week {v.EntryIndex + 1} (number {v.WeekOfYear} in year): (consignments between {v.RangeStart} and {v.RangeEnd})");
}
}
public List<ConsignmentRange> GetConsignments(IEnumerable<DateTime>consignments, DayOfWeek startOfWeek=DayOfWeek.Sunday)
{
return consignments
.OrderBy(v => v)
.GroupBy(v => v.AddDays(-(int)((7 - (int)startOfWeek) + (int)v.DayOfWeek) % 7))
.Select((v, idx) => new ConsignmentRange
{
EntryIndex = idx,
RangeStart = v.Key,
RangeEnd = v.Key.AddDays(6),
WeekOfYear = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
v.Key, CalendarWeekRule.FirstFourDayWeek, startOfWeek),
FirstDate = v.Min(),
LastDate = v.Max(),
FullWeek = (v.Distinct().Count() == 7)
}
)
.ToList();
}
我们还需要定义这个类(或者其中的一个子集,具体取决于您想要包含哪些数据):
public class ConsignmentRange
{
public int EntryIndex;
public int WeekOfYear;
public bool FullWeek;
public DateTime FirstDate;
public DateTime LastDate;
public DateTime RangeStart;
public DateTime RangeEnd;
}