我需要花一个月(定义为开始日期和结束日期)并返回该月每周的一组日期范围。一周定义为周日至周六。如果您在开始栏中双击Windows日期,那么可视化它的好方法是:
http://i54.tinypic.com/j58sh0.png
2011年10月有6周:10 / 1-10 / 1,10 / 2-10 / 8,10 / 9-10 / 15,10 / 16-10 / 22,10 / 23-10 / 29和10 / 30-10 / 31。
我可以将每周描述为结构:
struct Range
{
public DateTime Start;
public DateTime End;
public Range(DateTime start, DateTime end)
{
Start = start;
End = end;
}
}
我需要编写一个需要一个月的函数并返回一个范围数组。这是我的第一次尝试,它似乎起作用并解决了明显的边缘情况:
public static IEnumerable<Range> GetRange(DateTime start, DateTime end)
{
DateTime curStart = start;
DateTime curPtr = start;
do
{
if (curPtr.DayOfWeek == DayOfWeek.Saturday)
{
yield return new Range(curStart, curPtr);
curStart = curPtr.AddDays(1);
}
curPtr = curPtr.AddDays(1);
} while (curPtr <= end);
if(curStart <= end)
yield return new Range(curStart, end);
}
我想知道是否有更清洁或更明显的方法来做同样的事情。我并不过分关注性能,但我想提高代码可读性并使算法更简洁。也许有一个非常有创意的解决方案涉及单个LINQ表达式或其他东西。谢谢!
答案 0 :(得分:1)
这是基于Previti建议的简单增加7,准备国际使用。如果你的C#是&lt; 4.0,删除默认参数= DayOfWeek.Sunday
public static IEnumerable<Range> GetRange(DateTime start, DateTime end, DayOfWeek startOfTheWeek = DayOfWeek.Sunday)
{
if (start > end)
{
throw new ArgumentException();
}
// We "round" the dates to the beginning of the day each
start = start.Date;
end = end.Date;
// The first week. It could be "shorter" than normal. We return it "manually" here
// The 6 + startOfWeek - start.DayOfWeek will give us the number of days that you
// have to add to complete the week. It's mod 7. It's based on the idea that
// the starting day of the week is a parameter.
DateTime curDay = new DateTime(Math.Min(start.AddDays((6 + (int)startOfTheWeek - (int)start.DayOfWeek) % 7).Ticks, end.Ticks), start.Kind);
yield return new Range(start, curDay);
curDay = curDay.AddDays(1);
while (curDay <= end)
{
// Each time we add 7 (SIX) days. This is because the difference between
// as considered by the problem, it's only 6 * 24 hours (because the week
// doesn't end at 23:59:59 of the last day, but at the beginning of that day)
DateTime nextDay = new DateTime(Math.Min(curDay.AddDays(6).Ticks, end.Ticks), start.Kind);
yield return new Range(curDay, nextDay);
// The start of the next week
curDay = nextDay.AddDays(1);
}
}
一些小注释:Math.Min
没有为DateTime
定义,所以我通过Ticks
的{{1}}进行了比较并进行了比较。然后我重建了DateTime
。我总是使用DateTime
日期的DateTimeKind
。
调试start
代码时,请记住使用yield
或ToList
“实现”结果,否则代码将不会执行: - )