internal static DateTime GetNextDateByDayOfMonth(DateTime value, RecurrentMonths months, int dayOfMonth) { var match = default(RecurrentMonths); do { value = value.AddDays(1); if (dayOfMonth > DateTime.DaysInMonth(value.Year, value.Month)) { value = value.AddDays(-value.Day + 1).AddMonths(1).AddDays(-1); continue; } if (value.Day != dayOfMonth) { if (value.Day > dayOfMonth) { value = value.AddDays(DateTime.DaysInMonth(value.Year, value.Month) - value.Day).AddDays(dayOfMonth); } else { value = value.AddDays(dayOfMonth - value.Day); } } match = FlagsEnum.PowerOfTwo <RecurrentMonths>(value.Month - 1); }while ((months & match) != match || value.Day != dayOfMonth); return(value); }
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); }
/// <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="dayOfMonth"/> 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="dayOfMonth">The recurrent 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="months"/> is not specified /// -or- <paramref name="timesOfDay"/> is null or empty.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="dayOfMonth"/> is not between 1 and the greatest days of the specified <paramref name="months"/> /// -or- 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, int dayOfMonth, RecurrentMonths months, IEnumerable <TimeSpan> timesOfDay) : base(behavior, timesOfDay) { if (months == default(RecurrentMonths)) { throw new ArgumentException("Non specified argument.", "months"); } //determine upper bound of a leap year var upperBound = (from value in FlagsEnum.FlagValues <RecurrentMonths>(months) select DateTime.DaysInMonth(2012, FlagsEnum.PowerOfTwoExponent(value) + 1)).Max(); if (dayOfMonth < 1 || dayOfMonth > upperBound) { throw new ArgumentOutOfRangeException("dayOfMonth" , string.Format("Argument is not between 1 and the greatest days {0} of the specified months: {1}." , upperBound , months)); } DayOfMonth = dayOfMonth; 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) { }
/// <summary> /// Initializes a new instance of the <see cref="MonthlyRecurrence"/> class /// executed every <paramref name="dayOfMonth"/> of the specified <paramref name="months"/> /// at the specified <paramref name="timesOfDay"/>. /// </summary> /// <param name="dayOfMonth">The recurrent 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="months"/> is not specified /// -or- <paramref name="timesOfDay"/> is null or empty.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="dayOfMonth"/> is not between 1 and the greatest days of the specified <paramref name="months"/> /// -or- 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(int dayOfMonth, RecurrentMonths months, params TimeSpan[] timesOfDay) : this(RecurrenceBehavior.ShiftAndStandardTime, dayOfMonth, months, timesOfDay != null ? timesOfDay.AsEnumerable() : null) { }