/// <summary> /// Initializes a new instance of the <see cref="MonthlyRecurrence"/> class /// executed every <paramref name="weekDayOfMonth"/> of the specified <paramref name="months"/> /// at the specified <paramref name="timesOfDay"/>. /// </summary> /// <param name="behavior">The behavior regarding invalid times and ambiguous times.</param> /// <param name="weekDayOfMonth">The recurrent week day of month.</param> /// <param name="months">The recurrent months.</param> /// <param name="timesOfDay">The times of day the recurrence is executed.</param> /// <exception cref="ArgumentException"><paramref name="behavior"/> is not specified /// -or- <paramref name="weekDayOfMonth"/> is not specified /// -or- <paramref name="months"/> is not specified /// -or- <paramref name="timesOfDay"/> is null or empty.</exception> /// <exception cref="ArgumentOutOfRangeException">One of the specified <paramref name="timesOfDay"/> is lower than 00:00:00 or greater than or equal to 1.00:00:00.</exception> public MonthlyRecurrence(RecurrenceBehavior behavior, RecurrentWeekDaysOfMonth weekDayOfMonth, RecurrentMonths months, IEnumerable <TimeSpan> timesOfDay) : base(behavior, timesOfDay) { if (weekDayOfMonth == default(RecurrentWeekDaysOfMonth)) { throw new ArgumentException("Non specified argument.", "weekDayOfMonth"); } if (months == default(RecurrentMonths)) { throw new ArgumentException("Non specified argument.", "months"); } WeekDaysOfMonth = weekDayOfMonth; Months = months; }
/// <summary> /// Initializes a new instance of the <see cref="MonthlyRecurrence"/> class /// executed every <paramref name="weekDayOfMonth"/> of the specified <paramref name="months"/> /// at the specified <paramref name="timesOfDay"/>. /// </summary> /// <param name="behavior">The behavior regarding invalid times and ambiguous times.</param> /// <param name="weekDayOfMonth">The recurrent week day of month.</param> /// <param name="months">The recurrent months.</param> /// <param name="timesOfDay">The times of day the recurrence is executed.</param> /// <exception cref="ArgumentException"><paramref name="behavior"/> is not specified /// -or- <paramref name="weekDayOfMonth"/> is not specified /// -or- <paramref name="months"/> is not specified /// -or- <paramref name="timesOfDay"/> is null or empty.</exception> /// <exception cref="ArgumentOutOfRangeException">One of the specified <paramref name="timesOfDay"/> is lower than 00:00:00 or greater than or equal to 1.00:00:00.</exception> public MonthlyRecurrence(RecurrenceBehavior behavior, RecurrentWeekDaysOfMonth weekDayOfMonth, RecurrentMonths months, params TimeSpan[] timesOfDay) : this(behavior, weekDayOfMonth, months, timesOfDay != null ? timesOfDay.AsEnumerable() : null) { }
internal static DateTime GetNextDateByWeekDayOfMonth(DateTime value, RecurrentMonths months, RecurrentWeekDaysOfMonth weekDayOfMonth) { var firstOfMonth = value.AddDays(-value.Day + 1); //move to next month if necessary when any week days is requested if (weekDayOfMonth.AnyWeekDays) { var positionedDates = from positionedDate in DatesInPosition(firstOfMonth.Year, firstOfMonth.Month, weekDayOfMonth.Position) let dayOfWeek = FlagsEnum.PowerOfTwo <RecurrentWeekDays>(positionedDate.DayOfWeek) where (dayOfWeek & weekDayOfMonth.WeekDays) == dayOfWeek && positionedDate == value select positionedDate; if (positionedDates.Any()) { firstOfMonth = firstOfMonth.AddMonths(1); } } var nextDate = default(DateTime); do { var positionedDates = from positionedDate in DatesInPosition(firstOfMonth.Year, firstOfMonth.Month, weekDayOfMonth.Position) let dayOfWeek = FlagsEnum.PowerOfTwo <RecurrentWeekDays>(positionedDate.DayOfWeek) let month = FlagsEnum.PowerOfTwo <RecurrentMonths>(positionedDate.Month - 1) where (dayOfWeek & weekDayOfMonth.WeekDays) == dayOfWeek && (month & months) == month && positionedDate > value select positionedDate; //move to fourth position if necessary when all weekDays are requested in last position if (!weekDayOfMonth.AnyWeekDays && weekDayOfMonth.Position == WeekOfMonthPosition.Last && positionedDates.Count() > 1) { //consider positionedDates discontinuity only for continuous weekDays if (FlagsEnum.ContinuousFlagValues <RecurrentWeekDays>(weekDayOfMonth.WeekDays) && positionedDates.First().AddDays(positionedDates.Count() - 1) != positionedDates.Last()) { positionedDates = from positionedDate in DatesInPosition(firstOfMonth.Year, firstOfMonth.Month, WeekOfMonthPosition.Fourth) let dayOfWeek = FlagsEnum.PowerOfTwo <RecurrentWeekDays>(positionedDate.DayOfWeek) let month = FlagsEnum.PowerOfTwo <RecurrentMonths>(positionedDate.Month - 1) where (dayOfWeek & weekDayOfMonth.WeekDays) == dayOfWeek && (month & months) == month && positionedDate > value select positionedDate; } } nextDate = (weekDayOfMonth.AnyWeekDays && weekDayOfMonth.Position == WeekOfMonthPosition.Last) ? positionedDates.LastOrDefault() : positionedDates.FirstOrDefault(); firstOfMonth = firstOfMonth.AddMonths(1); }while (nextDate == default(DateTime)); return(nextDate); }