///------------------------------------------------------------------------------------------------- /// <summary> Adds a weekly in month event. </summary> /// /// <remarks> /// Adds weekly day-of-week events, can occur on multiple days of the week and at some /// interval by week. If the interval is null, all weeks [1...5.] are added, the 5th week /// does not occur every month. Its possible to set an odd pattern such as 1rst, 2nd week of /// every month. /// </remarks> /// /// <exception cref="ArgumentNullException"> /// Thrown when eventName is null or empty. /// </exception> /// <exception cref="ArgumentException"> /// Thrown when eventName is not unique or startDate > endDate. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when interval is less than 1 or greater than 5. /// </exception> /// /// <param name="eventName"> Name of the event, must be unique. </param> /// <param name="dayOff"> True if is a day off (is a workday). </param> /// <param name="dayOfWeek"> The day of week. </param> /// <param name="weekIntervals"> (Optional) The weekly intervals, If null every week, 1: 1 first week, 2: second week, 3: third week... Not every month will have a fifth week. </param> /// <param name="startDate"> (Optional) The date start, DateTime.MinValue if null. </param> /// <param name="endDate"> (Optional) The date end, DateTime.MaxValue if null. </param> /// /// <example> /// <code> /// // Mondays, first and third week. /// var weekIntervals = new int[] {1, 3}; /// CalendarDateTime.AddWeeklyInMonthEvent("Backups", false, DayOfWeek.Monday, weekIntervals); /// </code> /// </example> ///------------------------------------------------------------------------------------------------- public static void AddWeeklyInMonthEvent([CanBeNull] string eventName, bool dayOff, DayOfWeek dayOfWeek, [CanBeNull] IEnumerable <int> weekIntervals = null, DateTime?startDate = null, DateTime?endDate = null) { if (string.IsNullOrEmpty(eventName)) { throw new ArgumentNullException(nameof(eventName)); } if (ContainsEventKey(eventName)) { throw new ArgumentException(ErrorMessageKeyAlreadyAdded(nameof(eventName), eventName), nameof(eventName)); } const int minWeek = 1; const int maxWeek = 5; weekIntervals = weekIntervals?.Distinct().OrderBy(s => s).ToList() ?? Enumerable.Range(minWeek, maxWeek).ToList(); if (minWeek > weekIntervals.Min()) { throw new ArgumentOutOfRangeException(nameof(weekIntervals), ErrorMessageMinMaxOutOfRange(weekIntervals.Min(), nameof(weekIntervals), minWeek, maxWeek)); } if (weekIntervals.Max() > maxWeek) { throw new ArgumentOutOfRangeException(nameof(weekIntervals), ErrorMessageMinMaxOutOfRange(weekIntervals.Max(), nameof(weekIntervals), minWeek, maxWeek)); } var dateRange = new MinMaxSwapDate(startDate, endDate); WeeklyEventsDictionary.Add(eventName, new WeeklyInMonthEvent(dayOff, dayOfWeek, weekIntervals, dateRange.Min, dateRange.Max)); }
/// ------------------------------------------------------------------------------------------------- /// <summary> Adds a weekly event. </summary> /// /// <remarks> /// Add a weekly day-of-week events, can occur on multiple days of the week and at some skip /// interval. The baseDate is the date of the interval. Paydays typically follow this /// pattern. The number of occurrences may vary from month to month because some months are 4 /// weeks, some are 5 weeks. Another example; a meeting every two weeks on Tuesdays and /// Thursday within a date range. /// </remarks> /// /// <exception cref="ArgumentNullException"> /// Thrown when eventName is null or empty. /// </exception> /// <exception cref="ArgumentException"> /// Thrown when eventName is not unique or startDate > endDate. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when interval is less than one. /// </exception> /// <param name="eventName"> Name of the event, must be unique. </param> /// <param name="dayOff"> True if is a day off (is a workday). </param> /// <param name="daysOfWeek"> The days of week. This may be null. </param> /// <param name="seedWeek"> /// (Optional) (Optional if interval = 1) Seed date in the week of an occurrence. /// </param> /// <param name="interval"> /// (Optional) The week skip interval, 1=every week, 2 = every 2 weeks, 3 = 3 weeks... /// </param> /// <param name="startDate"> (Optional) The date start, DateTime.MinValue if null. </param> /// <param name="endDate"> (Optional) The date end, DateTime.MaxValue if null. </param> /// ------------------------------------------------------------------------------------------------- public static void AddWeeklyEvent([CanBeNull] string eventName, bool dayOff, [CanBeNull] IEnumerable <DayOfWeek> daysOfWeek, DateTime?seedWeek = null, int interval = 1, DateTime?startDate = null, DateTime?endDate = null) { if (string.IsNullOrEmpty(eventName)) { throw new ArgumentNullException(nameof(eventName)); } if (ContainsEventKey(eventName)) { throw new ArgumentException(ErrorMessageKeyAlreadyAdded(nameof(eventName), eventName), nameof(eventName)); } daysOfWeek = daysOfWeek?.Distinct().OrderBy(s => s).ToList(); if (daysOfWeek == null || !daysOfWeek.Any()) { throw new ArgumentNullException(nameof(daysOfWeek), ErrorMessageCannotBeNullOrEmpty(nameof(daysOfWeek))); } if (interval < 1) { throw new ArgumentOutOfRangeException(ErrorMessageZeroOrNegative(nameof(interval), interval)); } if (interval > 1 && seedWeek == null) { throw new ArgumentNullException(nameof(seedWeek), "If interval > 1, then " + nameof(seedWeek) + " cannot be null."); } var seed = seedWeek ?? DateTime.MinValue; var dateRange = new MinMaxSwapDate(startDate, endDate); WeeklyEventsDictionary.Add(eventName, new WeeklyEvent(dayOff, interval, daysOfWeek, seed, dateRange.Min, dateRange.Max)); }