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