public override IList <IPeriod> Evaluate(IDateTime referenceDate, DateTime periodStart, DateTime periodEnd, bool includeReferenceDateInResults) { // Ensure the reference date is associated with the time zone if (referenceDate.AssociatedObject == null) { referenceDate.AssociatedObject = TimeZone; } List <ITimeZoneInfo> infos = new List <ITimeZoneInfo>(TimeZone.TimeZoneInfos); // Evaluate extra time periods, without re-evaluating ones that were already evaluated if ((EvaluationStartBounds == DateTime.MaxValue && EvaluationEndBounds == DateTime.MinValue) || (periodEnd.Equals(EvaluationStartBounds)) || (periodStart.Equals(EvaluationEndBounds))) { foreach (ITimeZoneInfo curr in infos) { IEvaluator evaluator = curr.GetService(typeof(IEvaluator)) as IEvaluator; Debug.Assert(curr.Start != null, "TimeZoneInfo.Start must not be null."); Debug.Assert(curr.Start.TZID == null, "TimeZoneInfo.Start must not have a time zone reference."); Debug.Assert(evaluator != null, "TimeZoneInfo.GetService(typeof(IEvaluator)) must not be null."); // Time zones must include an effective start date/time // and must provide an evaluator. if (evaluator != null) { // Set the start bounds if (EvaluationStartBounds > periodStart) { EvaluationStartBounds = periodStart; } // FIXME: 5 years is an arbitrary number, to eliminate the need // to recalculate time zone information as much as possible. DateTime offsetEnd = periodEnd.AddYears(5); // Adjust our reference date to never fall out of bounds with // the time zone information var tziReferenceDate = referenceDate; if (tziReferenceDate.LessThan(curr.Start)) { tziReferenceDate = curr.Start; } // Determine the UTC occurrences of the Time Zone observances IList <IPeriod> periods = evaluator.Evaluate( tziReferenceDate, periodStart, offsetEnd, includeReferenceDateInResults); foreach (IPeriod period in periods) { if (!Periods.Contains(period)) { Periods.Add(period); } Occurrence o = new Occurrence(curr, period); if (!m_Occurrences.Contains(o)) { m_Occurrences.Add(o); } } if (EvaluationEndBounds == DateTime.MinValue || EvaluationEndBounds < offsetEnd) { EvaluationEndBounds = offsetEnd; } } } ProcessOccurrences(referenceDate); } else { if (EvaluationEndBounds != DateTime.MinValue && periodEnd > EvaluationEndBounds) { Evaluate(referenceDate, EvaluationEndBounds, periodEnd, includeReferenceDateInResults); } } return(Periods); }