/// <summary> /// This is used to expand one or more months by day of the week. It is used by the monthly and yearly /// frequencies. /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="dates">A reference to the collection of current instances that have been generated</param> /// <returns>The number of instances in the collection. If zero, subsequent rules don't have to be /// checked as there's nothing else to do.</returns> /// <remarks>If an expanded date is invalid, it will be discarded</remarks> public static int ByDayInMonths(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; DayOfWeek dow; int expIdx, instance, count = dates.Count; DayInstanceCollection byDay = r.ByDay; // Don't bother if either collection is empty if (count != 0 && byDay.Count != 0) { for (int idx = 0; idx < count; idx++) { rdt = dates[0]; dates.RemoveAt(0); // Expand the date/time by adding a new entry for each week day instance specified for (expIdx = 0; expIdx < byDay.Count; expIdx++) { instance = byDay[expIdx].Instance; dow = byDay[expIdx].DayOfWeek; if (instance == 0) { // Expand to every specified day of the week // in the month. rdtNew = new RecurDateTime(rdt) { Day = 1 }; rdtNew.AddDays(((int)dow + 7 - (int)rdtNew.DayOfWeek) % 7); while (rdtNew.IsValidDate() && rdtNew.Year == rdt.Year && rdtNew.Month == rdt.Month) { dates.Add(new RecurDateTime(rdtNew)); rdtNew.AddDays(7); } continue; } if (instance > 0) { // Add the nth instance of the day of the week rdtNew = new RecurDateTime(rdt) { Day = 1 }; rdtNew.AddDays((((int)dow + 7 - (int)rdtNew.DayOfWeek) % 7) + ((instance - 1) * 7)); } else { // Add the nth instance of the day of the week // from the end of the month. rdtNew = new RecurDateTime(rdt) { Day = DateTime.DaysInMonth(rdt.Year, rdt.Month + 1) }; rdtNew.AddDays(0 - (((int)rdtNew.DayOfWeek + 7 - (int)dow) % 7) + ((instance + 1) * 7)); } // If not in the year, discard it if (rdtNew.Year != rdt.Year || rdtNew.Month != rdt.Month) { continue; } dates.Add(new RecurDateTime(rdtNew)); } } } return(dates.Count); }