Я имею в виду, что вы могли бы придумать что-то уродливое и непонятное, основанное на формулах и избегающее циклов, но это будет уродливо и непонятно, так что подвержено ошибкам и беде на обслуживание, и совсем не весело придумать.
Вместо этого просто придумайте, что легко написать с помощью циклов, а затем скройте циклов с помощью LINQ:
static class DateTimeExtensions {
private static IEnumerable<DateTime> DaysOfMonth(int year, int month) {
return Enumerable.Range(1, DateTime.DaysInMonth(year, month))
.Select(day => new DateTime(year, month, day));
}
public static DateTime NthDayOfMonthFrom(
this HashSet<DayOfWeek> daysOfWeek,
int year,
int month,
int nth
) {
return
DateTimeExtensions.DaysOfMonth(year, month)
.Where(
date => daysOfWeek.Contains(date.DayOfWeek)
)
.Skip(nth - 1)
.First();
}
}
Использование:
var daysOfWeek = new HashSet<DayOfWeek> {
DayOfWeek.Monday, DayOfWeek.Wednesday, DayOfWeek.Friday
};
DateTime date = daysOfWeek.NthDayOfMonthFrom(2011, 6, 3));
Assert.Equal(date, new DateTime(2011, 6, 6));
Аналогично, используя Reverse
, вы можете легко написать NthLastDayOfWeekFrom
. Я оставлю это вам, чтобы придумать лучшее имя.