Ejemplo n.º 1
0
        /// <summary>
        ///     Evaluates the specified reference date.
        /// </summary>
        /// <param name="referenceDate">The reference date.</param>
        /// <param name="periodStart">The period start.</param>
        /// <param name="periodEnd">The period end.</param>
        /// <param name="includeReferenceDateInResults">
        ///     if set to <c>true</c> [include reference date in results].
        /// </param>
        /// <returns></returns>
        public override ISet <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;
            }

            var 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)
                {
                    var 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.
                    // 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
                    IDateTime tziReferenceDate = referenceDate;
                    if (tziReferenceDate.LessThan(curr.Start))
                    {
                        tziReferenceDate = curr.Start;
                    }

                    // Determine the UTC occurrences of the Time Zone observances
                    ISet <IPeriod> periods = evaluator.Evaluate(
                        tziReferenceDate,
                        periodStart,
                        offsetEnd,
                        includeReferenceDateInResults);

                    foreach (IPeriod period in periods)
                    {
                        Periods.Add(period);

                        var o = new Occurrence(curr, period);
                        _occurancesLookup.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);
        }