/// <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 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); rdtNew.Month = byMonth[expIdx] - 1; dates.Add(rdtNew); } } } return(dates.Count); }
/// <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 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> /// 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 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> /// 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 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> /// This is used to find the next instance of the minutely 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.AddMinutes(r.Interval); if (RecurDateTime.Compare(last, end, RecurDateTime.DateTimePart.Minute) > 0 || RecurDateTime.Compare(last, to, RecurDateTime.DateTimePart.Minute) > 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); rdtNew.Month = 0; rdtNew.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 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 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> /// 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> /// 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> /// 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); }