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;
}