/** * Returns a list of start dates in the specified period represented by this recur. This method includes a base date * argument, which indicates the start of the fist occurrence of this recurrence. The base date is used to inject * default values to return a set of dates in the correct format. For example, if the search start date (start) is * Wed, Mar 23, 12:19PM, but the recurrence is Mon - Fri, 9:00AM - 5:00PM, the start dates returned should all be at * 9:00AM, and not 12:19PM. */ private HashSet <DateTime> GetDates(IDateTime seed, DateTime periodStart, DateTime periodEnd, int maxCount, IRecurrencePattern pattern, bool includeReferenceDateInResults) { var dates = new HashSet <DateTime>(); var originalDate = DateUtil.GetSimpleDateTimeData(seed); var seedCopy = DateUtil.GetSimpleDateTimeData(seed); if (includeReferenceDateInResults) { dates.Add(seedCopy); } // optimize the start time for selecting candidates // (only applicable where a COUNT is not specified) if (pattern.Count == int.MinValue) { var incremented = seedCopy; IncrementDate(ref incremented, pattern, pattern.Interval); while (incremented < periodStart) { seedCopy = incremented; IncrementDate(ref incremented, pattern, pattern.Interval); } } var expandBehavior = RecurrenceUtil.GetExpandBehaviorList(pattern); var invalidCandidateCount = 0; var noCandidateIncrementCount = 0; var candidate = DateTime.MinValue; while ((maxCount < 0) || (dates.Count < maxCount)) { if (pattern.Until != DateTime.MinValue && candidate != DateTime.MinValue && candidate > pattern.Until) { break; } if (periodEnd != null && candidate != DateTime.MinValue && candidate > periodEnd) { break; } if (pattern.Count >= 1 && (dates.Count + invalidCandidateCount) >= pattern.Count) { break; } var candidates = GetCandidates(seedCopy, pattern, expandBehavior); if (candidates.Count > 0) { noCandidateIncrementCount = 0; // sort candidates for identifying when UNTIL date is exceeded.. candidates.Sort(); for (var i = 0; i < candidates.Count; i++) { candidate = candidates[i]; // don't count candidates that occur before the original date.. if (candidate >= originalDate) { // candidates MAY occur before periodStart // For example, FREQ=YEARLY;BYWEEKNO=1 could return dates // from the previous year. // // candidates exclusive of periodEnd.. if (candidate >= periodEnd) { invalidCandidateCount++; } else if (pattern.Count >= 1 && (dates.Count + invalidCandidateCount) >= pattern.Count) { break; } else if (pattern.Until == DateTime.MinValue || candidate <= pattern.Until) { var utcCandidate = DateUtil.FromTimeZoneToTimeZone(candidate, DateUtil.GetZone(seed.TzId), DateTimeZone.Utc).ToDateTimeUtc(); if (!dates.Contains(candidate) && (pattern.Until == DateTime.MinValue || utcCandidate <= pattern.Until)) { dates.Add(candidate); } } } } } else { noCandidateIncrementCount++; if ((maxIncrementCount > 0) && (noCandidateIncrementCount > maxIncrementCount)) { break; } } IncrementDate(ref seedCopy, pattern, pattern.Interval); } // sort final list.. return(dates); }
/** * Returns a list of start dates in the specified period represented by this recur. This method includes a base date * argument, which indicates the start of the fist occurrence of this recurrence. The base date is used to inject * default values to return a set of dates in the correct format. For example, if the search start date (start) is * Wed, Mar 23, 12:19PM, but the recurrence is Mon - Fri, 9:00AM - 5:00PM, the start dates returned should all be at * 9:00AM, and not 12:19PM. */ private IList <DateTime> GetDates(IDateTime seed, DateTime periodStart, DateTime periodEnd, int maxCount, IRecurrencePattern pattern, bool includeReferenceDateInResults) { SortedList <DateTime, DateTime> dates = new SortedList <DateTime, DateTime>(); DateTime originalDate = DateUtil.GetSimpleDateTimeData(seed); DateTime seedCopy = DateUtil.GetSimpleDateTimeData(seed); if (includeReferenceDateInResults) { dates.Add(seedCopy, seedCopy); } // If the interval is set to zero, or our count prevents us // from getting additional items, then return with the reference // date only. if (pattern.Interval == 0 || (pattern.Count != int.MinValue && pattern.Count <= dates.Count)) { return(dates.Values); } // optimize the start time for selecting candidates // (only applicable where a COUNT is not specified) if (pattern.Count == int.MinValue) { DateTime incremented = seedCopy; // FIXME: we can more aggresively increment here when // the difference between dates is greater. IncrementDate(ref incremented, pattern, pattern.Interval); while (incremented < periodStart) { seedCopy = incremented; IncrementDate(ref incremented, pattern, pattern.Interval); } } bool?[] expandBehavior = RecurrenceUtil.GetExpandBehaviorList(pattern); int invalidCandidateCount = 0; int noCandidateIncrementCount = 0; DateTime candidate = DateTime.MinValue; while ((maxCount < 0) || (dates.Count < maxCount)) { if (pattern.Until != DateTime.MinValue && candidate != DateTime.MinValue && candidate > pattern.Until) { break; } if (periodEnd != null && candidate != DateTime.MinValue && candidate > periodEnd) { break; } if (pattern.Count >= 1 && (dates.Count + invalidCandidateCount) >= pattern.Count) { break; } List <DateTime> candidates = GetCandidates(seedCopy, pattern, expandBehavior); if (candidates.Count > 0) { noCandidateIncrementCount = 0; // sort candidates for identifying when UNTIL date is exceeded.. candidates.Sort(); for (int i = 0; i < candidates.Count; i++) { candidate = candidates[i]; // don't count candidates that occur before the original date.. if (candidate >= originalDate) { // candidates MAY occur before periodStart // For example, FREQ=YEARLY;BYWEEKNO=1 could return dates // from the previous year. // // candidates exclusive of periodEnd.. if (candidate >= periodEnd) { invalidCandidateCount++; } else if (pattern.Count >= 1 && (dates.Count + invalidCandidateCount) >= pattern.Count) { break; } else if (pattern.Until == DateTime.MinValue || candidate <= pattern.Until) { if (!dates.ContainsKey(candidate)) { dates.Add(candidate, candidate); } } } } } else { noCandidateIncrementCount++; if ((maxIncrementCount > 0) && (noCandidateIncrementCount > maxIncrementCount)) { break; } } IncrementDate(ref seedCopy, pattern, pattern.Interval); } return(dates.Values); }
/** * Returns the the next date of this recurrence given a seed date * and start date. The seed date indicates the start of the fist * occurrence of this recurrence. The start date is the * starting date to search for the next recurrence. Return null * if there is no occurrence date after start date. * @return the next date in the recurrence series after startDate * @param seed the start date of this Recurrence's first instance * @param startDate the date to start the search */ private DateTime?GetNextDate(IDateTime referenceDate, DateTime periodStart, IRecurrencePattern pattern) { DateTime seedCopy = DateUtil.GetSimpleDateTimeData(referenceDate); // optimize the start time for selecting candidates // (only applicable where a COUNT is not specified) if (Pattern.Count == int.MinValue) { DateTime incremented = seedCopy; IncrementDate(ref incremented, pattern, pattern.Interval); while (incremented < periodStart) { seedCopy = incremented; IncrementDate(ref incremented, pattern, pattern.Interval); } } bool?[] expandBehaviors = RecurrenceUtil.GetExpandBehaviorList(pattern); int invalidCandidateCount = 0; int noCandidateIncrementCount = 0; DateTime candidate = DateTime.MinValue; while (true) { if (pattern.Until != DateTime.MinValue && candidate != DateTime.MinValue && candidate > pattern.Until) { break; } if (pattern.Count > 0 && invalidCandidateCount >= pattern.Count) { break; } List <DateTime> candidates = GetCandidates(seedCopy, pattern, expandBehaviors); if (candidates.Count > 0) { noCandidateIncrementCount = 0; // sort candidates for identifying when UNTIL date is exceeded.. candidates.Sort(); for (int i = 0; i < candidates.Count; i++) { candidate = candidates[i]; // don't count candidates that occur before the seed date.. if (candidate >= seedCopy) { // Candidate must be after startDate because // we want the NEXT occurrence if (candidate <= periodStart) { invalidCandidateCount++; } else if (pattern.Count > 0 && invalidCandidateCount >= pattern.Count) { break; } else if (pattern.Until == DateTime.MinValue || candidate <= pattern.Until) { return(candidate); } } } } else { noCandidateIncrementCount++; if ((maxIncrementCount > 0) && (noCandidateIncrementCount > maxIncrementCount)) { break; } } IncrementDate(ref seedCopy, pattern, pattern.Interval); } return(null); }
virtual public IList <Occurrence> GetOccurrences(IDateTime startTime, IDateTime endTime) { return(RecurrenceUtil.GetOccurrences(this, startTime, endTime, EvaluationIncludesReferenceDate)); }
virtual public IList <Occurrence> GetOccurrences(DateTime startTime, DateTime endTime) { return(RecurrenceUtil.GetOccurrences(this, new iCalDateTime(startTime), new iCalDateTime(endTime), EvaluationIncludesReferenceDate)); }
virtual public void ClearEvaluation() { RecurrenceUtil.ClearEvaluation(this); }
virtual public IList <Occurrence> GetOccurrences(DateTime dt) { return(RecurrenceUtil.GetOccurrences(this, new iCalDateTime(dt), EvaluationIncludesReferenceDate)); }
virtual public IList <Occurrence> GetOccurrences(DateTime startTime, DateTime endTime) { return(RecurrenceUtil.GetOccurrences(this, new iCalDateTime(startTime), new iCalDateTime(endTime), true)); }
virtual public IList <Occurrence> GetOccurrences(IDateTime startTime, IDateTime endTime) { return(RecurrenceUtil.GetOccurrences(this, startTime, endTime, true)); }
virtual public IList <Occurrence> GetOccurrences(DateTime dt) { return(RecurrenceUtil.GetOccurrences(this, new iCalDateTime(dt), true)); }
virtual public IList <Occurrence> GetOccurrences(IDateTime dt) { return(RecurrenceUtil.GetOccurrences(this, dt, true)); }
virtual public HashSet <Occurrence> GetOccurrences(IDateTime dt) { return(RecurrenceUtil.GetOccurrences(this, dt, EvaluationIncludesReferenceDate)); }