/// <summary> /// This is used to find the starting point for the weekly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { RecurDateTime rdtWeek, rdt = new RecurDateTime(start); int adjust; // Get the difference between the recurrence start and the limiting range start DateTime dtStart = start.ToDateTime().Date.AddDays(0 - r.weekdayOffset); DateTime dtFrom = from.ToDateTime().Date; dtFrom = dtFrom.AddDays(0 - ((int)dtFrom.DayOfWeek + 7 - (int)r.WeekStart) % 7); // Adjust the date so that it's in range if(dtStart < dtFrom) { TimeSpan ts = dtFrom - dtStart; adjust = (ts.Days / 7) + r.Interval - 1; rdt.AddDays((adjust - (adjust % r.Interval)) * 7); } // If the start of the week is after the ranges, stop now rdtWeek = new RecurDateTime(rdt); rdtWeek.AddDays(0 - r.weekdayOffset); if(RecurDateTime.Compare(rdtWeek, end, RecurDateTime.DateTimePart.Day) > 0 || RecurDateTime.Compare(rdtWeek, to, RecurDateTime.DateTimePart.Day) > 0) return null; return rdt; }
/// <summary> /// This is used to expand the yearly frequency by month /// </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>This may generate invalid dates (i.e. June 31st). These will be removed later.</remarks> public int ByMonth(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, count = dates.Count; UniqueIntegerCollection byMonth = r.ByMonth; // Don't bother if either collection is empty if (count != 0 && byMonth.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 month specified for (expIdx = 0; expIdx < byMonth.Count; expIdx++) { rdtNew = new RecurDateTime(rdt) { Month = byMonth[expIdx] - 1 }; dates.Add(rdtNew); } } } return(dates.Count); }
/// <summary> /// This is used to find the starting point for the daily frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { RecurDateTime rdt = new RecurDateTime(start); int adjust; // Get the difference between the recurrence start and the limiting range start DateTime dtStart = start.ToDateTime().Date, dtFrom = from.ToDateTime().Date; // Adjust the date so that it's in range if (dtStart < dtFrom) { TimeSpan ts = dtFrom - dtStart; adjust = ts.Days + r.Interval - 1; rdt.AddDays(adjust - (adjust % r.Interval)); } if (RecurDateTime.Compare(rdt, end, RecurDateTime.DateTimePart.Day) > 0 || RecurDateTime.Compare(rdt, to, RecurDateTime.DateTimePart.Day) > 0) { return(null); } return(rdt); }
/// <summary> /// This is used to expand by second /// </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 a date in the collection is invalid, it will be discarded</remarks> public static int BySecond(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, count = dates.Count; UniqueIntegerCollection bySecond = r.BySecond; // Don't bother if either collection is empty if (count != 0 && bySecond.Count != 0) { for (int idx = 0; idx < count; idx++) { rdt = dates[0]; dates.RemoveAt(0); // If not valid, discard it if (!rdt.IsValidDate()) { continue; } // Expand the date/time by adding a new entry for each second specified for (expIdx = 0; expIdx < bySecond.Count; expIdx++) { rdtNew = new RecurDateTime(rdt); rdtNew.Second = bySecond[expIdx]; dates.Add(rdtNew); } } } return(dates.Count); }
/// <summary> /// This is used to find the starting point for the secondly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { RecurDateTime rdt = new RecurDateTime(start); int adjust; if (RecurDateTime.Compare(start, from, RecurDateTime.DateTimePart.Hour) < 0) { // Get the difference between the recurrence start and the limiting range start DateTime dtStart = start.ToDateTime(), dtFrom = from.ToDateTime(); // Adjust the date/time so that it's in range TimeSpan ts = dtFrom - dtStart; adjust = (int)ts.TotalSeconds + r.Interval - 1; rdt.AddSeconds(adjust - (adjust % r.Interval)); } if (RecurDateTime.Compare(rdt, end, RecurDateTime.DateTimePart.Hour) > 0 || RecurDateTime.Compare(rdt, to, RecurDateTime.DateTimePart.Hour) > 0) { return(null); } return(rdt); }
/// <summary> /// This is used to find the starting point for the minutely frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { RecurDateTime rdt = new RecurDateTime(start); int adjust; if(RecurDateTime.Compare(start, from, RecurDateTime.DateTimePart.Hour) < 0) { // Get the difference between the recurrence start and the limiting range start DateTime dtStart = start.ToDateTime().AddSeconds(0 - start.Second), dtFrom = from.ToDateTime().AddSeconds(0 - from.Second); // Adjust the date/time so that it's in range TimeSpan ts = dtFrom - dtStart; adjust = (int)ts.TotalMinutes + r.Interval - 1; rdt.AddMinutes(adjust - (adjust % r.Interval)); } if(RecurDateTime.Compare(rdt, end, RecurDateTime.DateTimePart.Hour) > 0 || RecurDateTime.Compare(rdt, to, RecurDateTime.DateTimePart.Hour) > 0) return null; return rdt; }
/// <summary> /// This is used to find the starting point for the weekly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { RecurDateTime rdtWeek, rdt = new RecurDateTime(start); int adjust; // Get the difference between the recurrence start and the limiting range start DateTime dtStart = start.ToDateTime().Date.AddDays(0 - r.weekdayOffset); DateTime dtFrom = from.ToDateTime().Date; dtFrom = dtFrom.AddDays(0 - ((int)dtFrom.DayOfWeek + 7 - (int)r.WeekStart) % 7); // Adjust the date so that it's in range if (dtStart < dtFrom) { TimeSpan ts = dtFrom - dtStart; adjust = (ts.Days / 7) + r.Interval - 1; rdt.AddDays((adjust - (adjust % r.Interval)) * 7); } // If the start of the week is after the ranges, stop now rdtWeek = new RecurDateTime(rdt); rdtWeek.AddDays(0 - r.weekdayOffset); if (RecurDateTime.Compare(rdtWeek, end, RecurDateTime.DateTimePart.Day) > 0 || RecurDateTime.Compare(rdtWeek, to, RecurDateTime.DateTimePart.Day) > 0) { return(null); } return(rdt); }
/// <summary> /// This is used to find the next instance of the yearly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="end">The recurrence end date</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <param name="last">This is used to pass in the last instance date calculated and return the next /// instance date</param> /// <returns>True if the recurrence has another instance or false if there are no more instances</returns> public bool FindNext(Recurrence r, RecurDateTime end, RecurDateTime to, RecurDateTime last) { last.Year += r.Interval; if(last.Year > end.Year || last.Year > to.Year) return false; return true; }
/// <summary> /// This is used to find the next instance of the secondly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="end">The recurrence end date</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <param name="last">This is used to pass in the last instance date calculated and return the next /// instance date</param> /// <returns>True if the recurrence has another instance or false if there are no more instances</returns> public bool FindNext(Recurrence r, RecurDateTime end, RecurDateTime to, RecurDateTime last) { last.AddSeconds(r.Interval); if(last > end || last > to) return false; return true; }
/// <summary> /// Copy constructor /// </summary> /// <param name="rdt">The recurrence date/time to copy</param> public RecurDateTime(RecurDateTime rdt) { year = rdt.Year; month = rdt.Month; day = rdt.Day; hour = rdt.Hour; minute = rdt.Minute; second = rdt.Second; }
/// <summary> /// This is used to find the next instance of the daily frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="end">The recurrence end date</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <param name="last">This is used to pass in the last instance date calculated and return the next /// instance date</param> /// <returns>True if the recurrence has another instance or false if there are no more instances</returns> public bool FindNext(Recurrence r, RecurDateTime end, RecurDateTime to, RecurDateTime last) { last.AddDays(r.Interval); if(RecurDateTime.Compare(last, end, RecurDateTime.DateTimePart.Day) > 0 || RecurDateTime.Compare(last, to, RecurDateTime.DateTimePart.Day) > 0) return false; return true; }
/// <summary> /// This is used to find the next instance of the yearly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="end">The recurrence end date</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <param name="last">This is used to pass in the last instance date calculated and return the next /// instance date</param> /// <returns>True if the recurrence has another instance or false if there are no more instances</returns> public bool FindNext(Recurrence r, RecurDateTime end, RecurDateTime to, RecurDateTime last) { last.Year += r.Interval; if (last.Year > end.Year || last.Year > to.Year) { return(false); } return(true); }
/// <summary> /// This is used to find the next instance of the secondly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="end">The recurrence end date</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <param name="last">This is used to pass in the last instance date calculated and return the next /// instance date</param> /// <returns>True if the recurrence has another instance or false if there are no more instances</returns> public bool FindNext(Recurrence r, RecurDateTime end, RecurDateTime to, RecurDateTime last) { last.AddSeconds(r.Interval); if (last > end || last > to) { return(false); } return(true); }
//===================================================================== /// <summary> /// Compares this instance to a specified object and returns an indication of their relative values /// </summary> /// <param name="obj">An object to compare or null</param> /// <returns>Returns -1 if this instance is less than the value, 0 if they are equal, or 1 if this /// instance is greater than the value or the value is null.</returns> /// <exception cref="ArgumentException">This is thrown if the object to be compared is not a /// <c>RecurDateTime</c>.</exception> public int CompareTo(object obj) { RecurDateTime rd = obj as RecurDateTime; if (rd == null) { throw new ArgumentException(LR.GetString("ExRDTBadCompareObject")); } return(RecurDateTime.Compare(this, rd)); }
/// <summary> /// This is used to find the next instance of the daily frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="end">The recurrence end date</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <param name="last">This is used to pass in the last instance date calculated and return the next /// instance date</param> /// <returns>True if the recurrence has another instance or false if there are no more instances</returns> public bool FindNext(Recurrence r, RecurDateTime end, RecurDateTime to, RecurDateTime last) { last.AddDays(r.Interval); if (RecurDateTime.Compare(last, end, RecurDateTime.DateTimePart.Day) > 0 || RecurDateTime.Compare(last, to, RecurDateTime.DateTimePart.Day) > 0) { return(false); } return(true); }
/// <summary> /// This is overridden to allow proper comparison of RecurDateTime objects /// </summary> /// <param name="obj">The object to which this instance is compared</param> /// <returns>Returns true if the object equals this instance, false if it does not</returns> public override bool Equals(object obj) { RecurDateTime r = obj as RecurDateTime; if (r == null) { return(false); } return(year == r.Year && month == r.Month && day == r.Day && hour == r.Hour && minute == r.Minute && second == r.Second); }
/// <summary> /// This is used to expand the yearly frequency by week number /// </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 int ByWeekNo(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, week, yearWeeks, count = dates.Count; UniqueIntegerCollection byWeekNo = r.ByWeekNo; // Don't bother if either collection is empty if (count != 0 && byWeekNo.Count != 0) { for (int idx = 0; idx < count; idx++) { rdt = dates[0]; yearWeeks = DateUtils.WeeksInYear(rdt.Year, r.WeekStart); dates.RemoveAt(0); // Expand the date/time by adding a new entry for each week number specified for (expIdx = 0; expIdx < byWeekNo.Count; expIdx++) { week = byWeekNo[expIdx]; // If not in the year, discard it if ((week == 53 || week == -53) && yearWeeks == 52) { continue; } if (week > 0) { rdtNew = new RecurDateTime(DateUtils.DateFromWeek(rdt.Year, week, r.WeekStart, r.weekdayOffset)); } else { rdtNew = new RecurDateTime(DateUtils.DateFromWeek(rdt.Year, yearWeeks + week + 1, r.WeekStart, r.weekdayOffset)); } rdtNew.Hour = rdt.Hour; rdtNew.Minute = rdt.Minute; rdtNew.Second = rdt.Second; dates.Add(rdtNew); } } } return(dates.Count); }
//===================================================================== /// <summary> /// Returns a value indicating whether two specified instances of RecurDateTime are equal /// </summary> /// <param name="r1">The first date/time to compare</param> /// <param name="r2">The second date/time to compare</param> /// <returns>Returns true if the date/times are equal, false if they are not</returns> public static bool Equals(RecurDateTime r1, RecurDateTime r2) { if ((object)r1 == null && (object)r2 == null) { return(true); } if ((object)r1 == null) { return(false); } return(r1.Equals(r2)); }
/// <summary> /// This is used to expand the yearly frequency by year day /// </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 int ByYearDay(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, yearDay, count = dates.Count; UniqueIntegerCollection byYearDay = r.ByYearDay; // Don't bother if either collection is empty if (count != 0 && byYearDay.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 year day specified for (expIdx = 0; expIdx < byYearDay.Count; expIdx++) { yearDay = byYearDay[expIdx]; rdtNew = new RecurDateTime(rdt) { Month = 0, Day = 1 }; // From start of year or end of year? if (yearDay > 0) { rdtNew.AddDays(yearDay - 1); } else { rdtNew.Year++; rdtNew.AddDays(yearDay); } // If not in the year, discard it if (rdtNew.Year != rdt.Year) { continue; } dates.Add(rdtNew); } } } return(dates.Count); }
/// <summary> /// This is used to expand by month day /// </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 ByMonthDay(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, monthDay, count = dates.Count; UniqueIntegerCollection byMonthDay = r.ByMonthDay; // Don't bother if either collection is empty if (count != 0 && byMonthDay.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 month day specified for (expIdx = 0; expIdx < byMonthDay.Count; expIdx++) { monthDay = byMonthDay[expIdx]; rdtNew = new RecurDateTime(rdt) { Day = 1 }; // From start of month or end of month? if (monthDay > 0) { rdtNew.AddDays(monthDay - 1); } else { rdtNew.AddMonths(1); rdtNew.AddDays(monthDay); } // If not in the month, discard it if (rdtNew.Month != rdt.Month) { continue; } dates.Add(rdtNew); } } } return(dates.Count); }
/// <summary> /// This is used to find the next instance of the weekly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="end">The recurrence end date</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <param name="last">This is used to pass in the last instance date calculated and return the next /// instance date</param> /// <returns>True if the recurrence has another instance or false if there are no more instances</returns> public bool FindNext(Recurrence r, RecurDateTime end, RecurDateTime to, RecurDateTime last) { RecurDateTime rdtWeek; last.AddDays(r.Interval * 7); // For this one, compare the week start date rdtWeek = new RecurDateTime(last); rdtWeek.AddDays(0 - r.weekdayOffset); if(RecurDateTime.Compare(rdtWeek, end, RecurDateTime.DateTimePart.Day) > 0 || RecurDateTime.Compare(rdtWeek, to, RecurDateTime.DateTimePart.Day) > 0) return false; return true; }
/// <summary> /// This is used to find the next instance of the weekly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="end">The recurrence end date</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <param name="last">This is used to pass in the last instance date calculated and return the next /// instance date</param> /// <returns>True if the recurrence has another instance or false if there are no more instances</returns> public bool FindNext(Recurrence r, RecurDateTime end, RecurDateTime to, RecurDateTime last) { RecurDateTime rdtWeek; last.AddDays(r.Interval * 7); // For this one, compare the week start date rdtWeek = new RecurDateTime(last); rdtWeek.AddDays(0 - r.weekdayOffset); if (RecurDateTime.Compare(rdtWeek, end, RecurDateTime.DateTimePart.Day) > 0 || RecurDateTime.Compare(rdtWeek, to, RecurDateTime.DateTimePart.Day) > 0) { return(false); } return(true); }
/// <summary> /// This is used to find the starting point for the yearly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { int adjust; RecurDateTime rdt = new RecurDateTime(start); // Adjust the year if the starting date is before the limiting range start date if(rdt.Year < from.Year) { adjust = from.Year - rdt.Year + r.Interval - 1; rdt.Year += (adjust - (adjust % r.Interval)); } if(rdt.Year > end.Year || rdt.Year > to.Year) return null; return rdt; }
/// <summary> /// This is used to find the starting point for the monthly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { int adjust; RecurDateTime rdt = new RecurDateTime(start); // Adjust the date if the starting date is before the limiting range start date if(RecurDateTime.Compare(rdt, from, RecurDateTime.DateTimePart.Month) < 0) { adjust = ((from.Year - rdt.Year) * 12) + from.Month - rdt.Month + r.Interval - 1; rdt.AddMonths(adjust - (adjust % r.Interval)); } if(RecurDateTime.Compare(rdt, end, RecurDateTime.DateTimePart.Month) > 0 || RecurDateTime.Compare(rdt, to, RecurDateTime.DateTimePart.Month) > 0) return null; return rdt; }
/// <summary> /// This is used to find the starting point for the yearly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { int adjust; RecurDateTime rdt = new RecurDateTime(start); // Adjust the year if the starting date is before the limiting range start date if (rdt.Year < from.Year) { adjust = from.Year - rdt.Year + r.Interval - 1; rdt.Year += (adjust - (adjust % r.Interval)); } if (rdt.Year > end.Year || rdt.Year > to.Year) { return(null); } return(rdt); }
/// <summary> /// This is used to expand by month day /// </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 ByMonthDay(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, monthDay, count = dates.Count; UniqueIntegerCollection byMonthDay = r.ByMonthDay; // Don't bother if either collection is empty if(count != 0 && byMonthDay.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 month day specified for(expIdx = 0; expIdx < byMonthDay.Count; expIdx++) { monthDay = byMonthDay[expIdx]; rdtNew = new RecurDateTime(rdt); rdtNew.Day = 1; // From start of month or end of month? if(monthDay > 0) rdtNew.AddDays(monthDay - 1); else { rdtNew.AddMonths(1); rdtNew.AddDays(monthDay); } // If not in the month, discard it if(rdtNew.Month != rdt.Month) continue; dates.Add(rdtNew); } } return dates.Count; }
/// <summary> /// This is used to find the starting point for the monthly frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { int adjust; RecurDateTime rdt = new RecurDateTime(start); // Adjust the date if the starting date is before the limiting range start date if (RecurDateTime.Compare(rdt, from, RecurDateTime.DateTimePart.Month) < 0) { adjust = ((from.Year - rdt.Year) * 12) + from.Month - rdt.Month + r.Interval - 1; rdt.AddMonths(adjust - (adjust % r.Interval)); } if (RecurDateTime.Compare(rdt, end, RecurDateTime.DateTimePart.Month) > 0 || RecurDateTime.Compare(rdt, to, RecurDateTime.DateTimePart.Month) > 0) { return(null); } return(rdt); }
/// <summary> /// This is used to find the starting point for the daily frequency /// </summary> /// <param name="r">A reference to the recurrence</param> /// <param name="start">The recurrence start date</param> /// <param name="end">The recurrence end date</param> /// <param name="from">The start date of the range limiting the instances generated</param> /// <param name="to">The end date of the range limiting the instances generated</param> /// <returns>The first instance date or null if there are no more instances</returns> public RecurDateTime FindStart(Recurrence r, RecurDateTime start, RecurDateTime end, RecurDateTime from, RecurDateTime to) { RecurDateTime rdt = new RecurDateTime(start); int adjust; // Get the difference between the recurrence start and the limiting range start DateTime dtStart = start.ToDateTime().Date, dtFrom = from.ToDateTime().Date; // Adjust the date so that it's in range if(dtStart < dtFrom) { TimeSpan ts = dtFrom - dtStart; adjust = ts.Days + r.Interval - 1; rdt.AddDays(adjust - (adjust % r.Interval)); } if(RecurDateTime.Compare(rdt, end, RecurDateTime.DateTimePart.Day) > 0 || RecurDateTime.Compare(rdt, to, RecurDateTime.DateTimePart.Day) > 0) return null; return rdt; }
/// <summary> /// This is used to expand one or more weeks by day of the week /// </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 ByDayInWeeks(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, 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); // If not valid, discard it if (!rdt.IsValidDate()) { continue; } // Expand the date/time by adding a new entry for each day of the week. As with filtering, // the instance number is ignored as it isn't useful here. For this, the "week" is the seven // day period starting on the occurrence date. for (expIdx = 0; expIdx < byDay.Count; expIdx++) { rdtNew = new RecurDateTime(rdt); rdtNew.AddDays((((int)byDay[expIdx].DayOfWeek + 7 - (int)r.WeekStart) % 7) - (((int)rdt.DayOfWeek + 7 - (int)r.WeekStart) % 7)); dates.Add(rdtNew); } } } return(dates.Count); }
/// <summary> /// Compares two <c>RecurDateTime</c> values and returns an integer that indicates their relationship. /// This version only compares up to the specified date/time part. /// </summary> /// <param name="r1">The first date/time</param> /// <param name="r2">The second date/time</param> /// <param name="part">The part up to which comparisons are made. Parts smaller than this are ignored.</param> /// <returns>Returns -1 if the first instance is less than the second, 0 if they are equal, or 1 if the /// first instance is greater than the second.</returns> public static int Compare(RecurDateTime r1, RecurDateTime r2, DateTimePart part) { // Cast as object for null checks or it goes recursive if ((object)r1 == null && (object)r2 == null) { return(0); } if ((object)r1 != null && (object)r2 == null) { return(1); } if ((object)r1 == null && (object)r2 != null) { return(-1); } if (r1.Year < r2.Year) { return(-1); } if (r1.Year > r2.Year) { return(1); } if (part == DateTimePart.Year) { return(0); } if (r1.Month < r2.Month) { return(-1); } if (r1.Month > r2.Month) { return(1); } if (part == DateTimePart.Month) { return(0); } if (r1.Day < r2.Day) { return(-1); } if (r1.Day > r2.Day) { return(1); } if (part == DateTimePart.Day) { return(0); } if (r1.Hour < r2.Hour) { return(-1); } if (r1.Hour > r2.Hour) { return(1); } if (part == DateTimePart.Hour) { return(0); } if (r1.Minute < r2.Minute) { return(-1); } if (r1.Minute > r2.Minute) { return(1); } if (part == DateTimePart.Minute) { return(0); } if (r1.Second < r2.Second) { return(-1); } if (r1.Second > r2.Second) { return(1); } return(0); }
/// <summary> /// This is used to expand by second /// </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 a date in the collection is invalid, it will be discarded</remarks> public static int BySecond(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, count = dates.Count; UniqueIntegerCollection bySecond = r.BySecond; // Don't bother if either collection is empty if(count != 0 && bySecond.Count != 0) for(int idx = 0; idx < count; idx++) { rdt = dates[0]; dates.RemoveAt(0); // If not valid, discard it if(!rdt.IsValidDate()) continue; // Expand the date/time by adding a new entry for each second specified for(expIdx = 0; expIdx < bySecond.Count; expIdx++) { rdtNew = new RecurDateTime(rdt); rdtNew.Second = bySecond[expIdx]; dates.Add(rdtNew); } } return dates.Count; }
/// <summary> /// This method is used to return all recurring instances between the two specified date/times based on /// the current settings. /// </summary> /// <param name="fromDate">The minimum date/time on or after which instances should occur.</param> /// <param name="toDate">The maximum date/time on or before which instances should occur.</param> /// <returns>Returns a <see cref="DateTimeCollection"/> of <see cref="DateTime" /> objects that represent /// the instances found between the two specified date/times.</returns> private DateTimeCollection GenerateInstances(DateTime fromDate, DateTime toDate) { RecurDateTimeCollection rdtc; RecurDateTime rdt; int idx, count, lastYear = -1; DateTimeCollection dcDates = new DateTimeCollection(); // If undefined or if the requested range is outside that of the recurrence, don't bother. Just // return an empty collection. Note that for defined recurrences that use a count, we'll always // have to expand it. if(frequency == RecurFrequency.Undefined || startDate > toDate || untilDate < fromDate) return dcDates; RecurDateTime start = new RecurDateTime(startDate), end = new RecurDateTime(untilDate), from = new RecurDateTime(fromDate), to = new RecurDateTime(toDate); RecurDateTime current = freqRules.FindStart(this, start, end, from, to); // If there's nothing to generate, stop now if(current == null) return dcDates; rdtc = new RecurDateTimeCollection(); // Initialize the filtering arrays. These help speed up the filtering process by letting us do one // look up as opposed to comparing all elements in the collection. Array.Clear(isSecondUsed, 0, isSecondUsed.Length); Array.Clear(isMinuteUsed, 0, isMinuteUsed.Length); Array.Clear(isHourUsed, 0, isHourUsed.Length); Array.Clear(isDayUsed, 0, isDayUsed.Length); Array.Clear(isMonthDayUsed, 0, isMonthDayUsed.Length); Array.Clear(isNegMonthDayUsed, 0, isNegMonthDayUsed.Length); Array.Clear(isYearDayUsed, 0, isYearDayUsed.Length); Array.Clear(isNegYearDayUsed, 0, isNegYearDayUsed.Length); Array.Clear(isMonthUsed, 0, isMonthUsed.Length); if(bySecond.Count != 0) foreach(int second in bySecond) isSecondUsed[second] = true; if(byMinute.Count != 0) foreach(int minute in byMinute) isMinuteUsed[minute] = true; if(byHour.Count != 0) foreach(int hour in byHour) isHourUsed[hour] = true; if(byMonth.Count != 0) foreach(int month in byMonth) isMonthUsed[month - 1] = true; // When filtering, the instance is ignored if(byDay.Count != 0) foreach(DayInstance di in byDay) isDayUsed[(int)di.DayOfWeek] = true; // Negative days are from the end of the month if(byMonthDay.Count != 0) foreach(int monthDay in byMonthDay) if(monthDay > 0) isMonthDayUsed[monthDay] = true; else isNegMonthDayUsed[0 - monthDay] = true; // Negative days are from the end of the year if(byYearDay.Count != 0) foreach(int yearDay in byYearDay) if(yearDay > 0) isYearDayUsed[yearDay] = true; else isNegYearDayUsed[0 - yearDay] = true; do { rdtc.Clear(); rdtc.Add(current); // The spec is rather vague about how some of the rules are used together. For example, it says // that rule parts for a period of time less than the frequency generally expand it. However, // an example for the MONTHLY frequency shows that when BYMONTHDAY and BYDAY are used together, // BYDAY acts as a filter for BYMONTHDAY not an expansion of the frequency. When used by // themselves, the rules in question do act as expansions. There are no examples for the yearly // frequency that show how all of the various combinations interact so I'm making some // assumptions based on an evaluation of what makes the most sense. switch(frequency) { case RecurFrequency.Yearly: // This one gets rather messy so it's separate ExpandYearly(rdtc); break; case RecurFrequency.Monthly: if(freqRules.ByMonth(this, rdtc) != 0) if(freqRules.ByYearDay(this, rdtc) != 0) { // If BYMONTHDAY and BYDAY are specified, expand by month day and filter by day. // If one but not the other or neither is specified, handle them in order as // usual. if(byMonthDay.Count != 0 && byDay.Count != 0) { if(Expand.ByMonthDay(this, rdtc) != 0) if(Filter.ByDay(this, rdtc) != 0) { // These always expand if used Expand.ByHour(this, rdtc); Expand.ByMinute(this, rdtc); Expand.BySecond(this, rdtc); } } else if(Expand.ByMonthDay(this, rdtc) != 0) if(freqRules.ByDay(this, rdtc) != 0) { // These always expand if used Expand.ByHour(this, rdtc); Expand.ByMinute(this, rdtc); Expand.BySecond(this, rdtc); } } break; default: // Everything else is fairly straightforward. We just expand or filter based on the // frequency type and what rules are specified. if(freqRules.ByMonth(this, rdtc) != 0) if(freqRules.ByYearDay(this, rdtc) != 0) if(freqRules.ByMonthDay(this, rdtc) != 0) if(freqRules.ByDay(this, rdtc) != 0) if(freqRules.ByHour(this, rdtc) != 0) if(freqRules.ByMinute(this, rdtc) != 0) freqRules.BySecond(this, rdtc); break; } // Sort the dates and remove invalid and duplicate dates rdtc.Sort(); for(idx = 0, count = rdtc.Count; idx < count; idx++) { rdt = rdtc[idx]; // If not valid, discard it. if(!rdt.IsValidDate()) { rdtc.RemoveAt(idx); idx--; count--; continue; } // Discard it if it falls on a holiday if(!canOccurOnHoliday) { // If this is the first call or the year changes, get the holidays in the date's year // and the next year. if(holDates == null || lastYear != rdt.Year) { holDates = new HashSet<DateTime>(holidays.HolidaysBetween(rdt.Year, rdt.Year + 1)); lastYear = rdt.Year; } // Note that we only compare the date part as the holiday's time probably will not match // the recurrence's time. if(holDates.Contains(rdt.ToDateTime().Date)) { rdtc.RemoveAt(idx); idx--; count--; continue; } } // Discard it if it's a duplicate if(idx != 0 && rdt == rdtc[idx - 1]) { rdtc.RemoveAt(idx); idx--; count--; continue; } } if(rdtc.Count != 0) { // Apply the BYSETPOS rule and remove entries prior to the start or past the end of the // ranges. if(bySetPos.Count != 0) { foreach(int nPos in bySetPos) { // Invert negative values. They'll select elements indexed from the end of the // array. if(nPos < 0) idx = nPos + rdtc.Count; else idx = nPos - 1; if(idx >= 0 && idx < rdtc.Count) if(rdtc[idx] >= start && rdtc[idx] <= end && rdtc[idx] >= from && rdtc[idx] <= to) dcDates.Add(rdtc[idx].ToDateTime()); } } else for(idx = 0; idx < rdtc.Count; idx++) if(rdtc[idx] >= start && rdtc[idx] <= end && rdtc[idx] >= from && rdtc[idx] <= to) dcDates.Add(rdtc[idx].ToDateTime()); // Handle MaxOccurrences property. Note that if it's used, it is assumed that the limiting // range starts at the recurrence start. Otherwise, we have no way of knowing how many // occurred between the recurrence start and the limiting range's start date. if(maxOccur != 0 && dcDates.Count > maxOccur) dcDates.RemoveRange(maxOccur, dcDates.Count - maxOccur); } // Loop until the end of the recurrence or the range } while(freqRules.FindNext(this, end, to, current) && (maxOccur == 0 || dcDates.Count < maxOccur)); // Sort the collection one last time. There's no guaranteed order of selection if BYSETPOS was used. dcDates.Sort(true); return dcDates; }
/// <summary> /// This is used to expand the yearly frequency by day of the week /// </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 int ByDay(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 year rdtNew = new RecurDateTime(rdt); rdtNew.Month = 0; rdtNew.Day = 1; rdtNew.AddDays(((int)dow + 7 - (int)rdtNew.DayOfWeek) % 7); while(rdtNew.Year == rdt.Year) { 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); rdtNew.Month = 0; rdtNew.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 year rdtNew = new RecurDateTime(rdt); rdtNew.Month = 11; rdtNew.Day = 31; 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) continue; dates.Add(new RecurDateTime(rdtNew)); } } return dates.Count; }
/// <summary> /// This is used to expand the yearly frequency by week number /// </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 int ByWeekNo(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, week, yearWeeks, count = dates.Count; UniqueIntegerCollection byWeekNo = r.ByWeekNo; // Don't bother if either collection is empty if(count != 0 && byWeekNo.Count != 0) for(int idx = 0; idx < count; idx++) { rdt = dates[0]; yearWeeks = DateUtils.WeeksInYear(rdt.Year, r.WeekStart); dates.RemoveAt(0); // Expand the date/time by adding a new entry for each week number specified for(expIdx = 0; expIdx < byWeekNo.Count; expIdx++) { week = byWeekNo[expIdx]; // If not in the year, discard it if((week == 53 || week == -53) && yearWeeks == 52) continue; if(week > 0) { rdtNew = new RecurDateTime(DateUtils.DateFromWeek(rdt.Year, week, r.WeekStart, r.weekdayOffset)); } else rdtNew = new RecurDateTime(DateUtils.DateFromWeek(rdt.Year, yearWeeks + week + 1, r.WeekStart, r.weekdayOffset)); rdtNew.Hour = rdt.Hour; rdtNew.Minute = rdt.Minute; rdtNew.Second = rdt.Second; dates.Add(rdtNew); } } return dates.Count; }
//===================================================================== /// <summary> /// Returns a value indicating whether two specified instances of RecurDateTime are equal /// </summary> /// <param name="r1">The first date/time to compare</param> /// <param name="r2">The second date/time to compare</param> /// <returns>Returns true if the date/times are equal, false if they are not</returns> public static bool Equals(RecurDateTime r1, RecurDateTime r2) { if((object)r1 == null && (object)r2 == null) return true; if((object)r1 == null) return false; return r1.Equals(r2); }
/// <summary> /// Compares two <c>RecurDateTime</c> values and returns an integer that indicates their relationship. /// This version only compares up to the specified date/time part. /// </summary> /// <param name="r1">The first date/time</param> /// <param name="r2">The second date/time</param> /// <param name="part">The part up to which comparisons are made. Parts smaller than this are ignored.</param> /// <returns>Returns -1 if the first instance is less than the second, 0 if they are equal, or 1 if the /// first instance is greater than the second.</returns> public static int Compare(RecurDateTime r1, RecurDateTime r2, DateTimePart part) { // Cast as object for null checks or it goes recursive if((object)r1 == null && (object)r2 == null) return 0; if((object)r1 != null && (object)r2 == null) return 1; if((object)r1 == null && (object)r2 != null) return -1; if(r1.Year < r2.Year) return -1; if(r1.Year > r2.Year) return 1; if(part == DateTimePart.Year) return 0; if(r1.Month < r2.Month) return -1; if(r1.Month > r2.Month) return 1; if(part == DateTimePart.Month) return 0; if(r1.Day < r2.Day) return -1; if(r1.Day > r2.Day) return 1; if(part == DateTimePart.Day) return 0; if(r1.Hour < r2.Hour) return -1; if(r1.Hour > r2.Hour) return 1; if(part == DateTimePart.Hour) return 0; if(r1.Minute < r2.Minute) return -1; if(r1.Minute > r2.Minute) return 1; if(part == DateTimePart.Minute) return 0; if(r1.Second < r2.Second) return -1; if(r1.Second > r2.Second) return 1; return 0; }
/// <summary> /// This is used to expand the yearly frequency by month /// </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>This may generate invalid dates (i.e. June 31st). These will be removed later.</remarks> public int ByMonth(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, count = dates.Count; UniqueIntegerCollection byMonth = r.ByMonth; // Don't bother if either collection is empty if(count != 0 && byMonth.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 month specified for(expIdx = 0; expIdx < byMonth.Count; expIdx++) { rdtNew = new RecurDateTime(rdt); rdtNew.Month = byMonth[expIdx] - 1; dates.Add(rdtNew); } } return dates.Count; }
/// <summary> /// This is used to expand the yearly frequency by day of the week /// </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 int ByDay(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 year rdtNew = new RecurDateTime(rdt) { Month = 0, Day = 1 }; rdtNew.AddDays(((int)dow + 7 - (int)rdtNew.DayOfWeek) % 7); while (rdtNew.Year == rdt.Year) { 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) { Month = 0, 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 year rdtNew = new RecurDateTime(rdt) { Month = 11, Day = 31 }; 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) { continue; } dates.Add(new RecurDateTime(rdtNew)); } } } return(dates.Count); }
/// <summary> /// Overload for greater than or equal operator /// </summary> /// <param name="r1">The first date/time object</param> /// <param name="r2">The second date/time object</param> /// <returns>True if r1 is greater than or equal to r2, false if not</returns> public static bool operator >=(RecurDateTime r1, RecurDateTime r2) { return(RecurDateTime.Compare(r1, r2) >= 0); }
/// <summary> /// This is used to expand one or more weeks by day of the week /// </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 ByDayInWeeks(Recurrence r, RecurDateTimeCollection dates) { RecurDateTime rdt, rdtNew; int expIdx, 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); // If not valid, discard it if(!rdt.IsValidDate()) continue; // Expand the date/time by adding a new entry for each day of the week. As with filtering, // the instance number is ignored as it isn't useful here. For this, the "week" is the seven // day period starting on the occurrence date. for(expIdx = 0; expIdx < byDay.Count; expIdx++) { rdtNew = new RecurDateTime(rdt); rdtNew.AddDays((((int)byDay[expIdx].DayOfWeek + 7 - (int)r.WeekStart) % 7) - (((int)rdt.DayOfWeek + 7 - (int)r.WeekStart) % 7)); dates.Add(rdtNew); } } return dates.Count; }