我试图找到给定月份(给定年份)的第n个DayOfWeek。
例如:我正在寻找5月的第三个星期六(2019年)。
我无法使用DayOfWeek
扩展方法提出可行的解决方案。我是否需要遍历整个月才能找到第三个星期六?
答案 0 :(得分:3)
您当然可以遍历整个月,但我认为这是一种更为优雅的方法(摘自here):
private static DateTime FindTheNthDayOfWeek(int year, int month, int nthOccurrence, DayOfWeek dayOfWeek)
{
if (month < 1 || month > 12)
{
throw new ArgumentOutOfRangeException("Invalid month");
}
if (nthOccurrence < 0 || nthOccurrence > 5)
{
throw new ArgumentOutOfRangeException("Invalid nth occurrence");
}
var dt = new DateTime(year, month, 1);
while (dt.DayOfWeek != dayOfWeek)
{
dt = dt.AddDays(1);
}
dt = dt.AddDays((nthOccurrence - 1) * 7);
if (dt.Month != month)
{
throw new ArgumentOutOfRangeException(string.Format("The given month has less than {0} {1}s", nthOccurrence, dayOfWeek));
}
return dt;
}
此私有方法不会在整个月中循环,但是一旦找到第一个DayOfWeek,它便已经停止。然后,您只需为每个第n次出现添加一个星期(减去已经添加的星期;-))。
答案 1 :(得分:1)
如果您谈论日期,则日期应与某些日历相关,例如我的公历。
public static class DataTimeExt
{
public static IEnumerable<DateTime> TakeWhileInclusive(this DateTime value,
Func<DateTime, bool> func)
{
DateTime dt = value;
yield return dt; //[first
while (func(dt = dt.AddDays(1))) yield return dt; //in between
yield return dt; //last]
}
}
然后您可以迭代日期直到周日,然后再添加14天。
var calendar = new GregorianCalendar();
var dates = new DateTime(2019, 5, 1, calendar)
.TakeWhileInclusive(dt => calendar.GetDayOfWeek(dt) != DayOfWeek.Sunday);
Console.WriteLine(dates.Last().AddDays(14));
答案 2 :(得分:1)
我创建了两个扩展方法,其中一个从日期获取下一个DayOfWeek(可选地包括日期本身),另一个从前一个DayOfWeek获取,具有相同的功能。
public static DateTime Next(
this DateTime source,
DayOfWeek dayOfWeek,
bool considerSameDate
) => ( dayOfWeek - source.DayOfWeek) is var difference
&& difference < (considerSameDate ? 0 : 1)
? source.AddDays(difference + 7)
: source.AddDays(difference)
;
和
public static DateTime Previous(
this DateTime source,
DayOfWeek dayOfWeek,
bool considerSameDate
) => dayOfWeek == source.DayOfWeek
? ( considerSameDate ? source : source.AddDays(-7) )
: source.AddDays(
( dayOfWeek - source.DayOfWeek ) is var difference
&& difference > 0
? difference - 7
: difference
);
有了这些,人们可以问你提出的问题:
var x = new System.DateTime(2019, 5, 1).Next(System.DayOfWeek.Saturday, true).AddDays(14);
我创建了一个新的DateTime(2019-05-01),在星期六致电Next,并将5/1作为候选者,然后加上14天,这使其成为2019年5月的第三个星期六。 >
答案 3 :(得分:1)
这很简单而且干净,没有循环。只是一点算术。
static DateTime? NthWeekDayOfMonth( int n, DayOfWeek dow, int year , int month)
{
DateTime startOfMonth = new DateTime( year, month, 1 ) ;
int offset = ( 7 + dow - startOfMonth.DayOfWeek ) % 7 ;
DateTime nthWeekDayOfMonth = startOfMonth
.AddDays( offset )
.AddDays( 7 * (n-1) )
;
bool isSameMonth = startOfMonth.Year == nthWeekDayOfMonth.Year
&& startOfMonth.Month == nthWeekDayOfMonth.Month
;
return isSameMonth
? nthWeekDayOfMonth
: (DateTime?) null
;
}