Exemplo n.º 1
0
        /// <summary>
        /// Returns the first transition which occurs strictly after the given instant.
        /// </summary>
        /// <remarks>
        /// If the given instant is before the starting year, the year of the given instant is
        /// adjusted to the beginning of the starting year. The first transition after the
        /// adjusted instant is determined. If the next adjustment is after the ending year, this
        /// method returns null; otherwise the next transition is returned.
        /// </remarks>
        /// <param name="instant">The <see cref="Instant"/> lower bound for the next transition.</param>
        /// <param name="standardOffset">The <see cref="Offset"/> standard offset.</param>
        /// <param name="previousSavings">The <see cref="Offset"/> savings adjustment at the given Instant.</param>
        /// <returns>The next transition, or null if there is no next transition. The transition may be
        /// infinite, i.e. after the end of representable time.</returns>
        internal Transition?Next(Instant instant, Offset standardOffset, Offset previousSavings)
        {
            Offset ruleOffset = YearOffset.GetRuleOffset(standardOffset, previousSavings);
            Offset newOffset  = standardOffset + Savings;

            LocalInstant safeLocal = instant.SafePlus(ruleOffset);
            int          targetYear;

            if (safeLocal < minLocalInstant)
            {
                // Asked for a transition after some point before the first transition: crop to first year (so we get the first transition)
                targetYear = FromYear;
            }
            else if (safeLocal >= maxLocalInstant)
            {
                // Asked for a transition after our final transition... or both are beyond the end of time (in which case
                // we can return an infinite transition). This branch will always be taken for transitions beyond the end
                // of time.
                return(maxLocalInstant == LocalInstant.AfterMaxValue ? new Transition(Instant.AfterMaxValue, newOffset) : (Transition?)null);
            }
            else if (safeLocal == LocalInstant.BeforeMinValue)
            {
                // We've been asked to find the next transition after some point which is a valid instant, but is before the
                // start of valid local time after applying the rule offset. For example, passing Instant.MinValue for a rule which says
                // "transition uses wall time, which is UTC-5". Proceed as if we'd been asked for something in -9998.
                // I *think* that works...
                targetYear = GregorianYearMonthDayCalculator.MinGregorianYear;
            }
            else
            {
                // Simple case: we were asked for a "normal" value in the range of years for which this recurrence is valid.
                int ignoredDayOfYear;
                targetYear = CalendarSystem.Iso.YearMonthDayCalculator.GetYear(safeLocal.DaysSinceEpoch, out ignoredDayOfYear);
            }

            LocalInstant transition = YearOffset.GetOccurrenceForYear(targetYear);

            Instant safeTransition = transition.SafeMinus(ruleOffset);

            if (safeTransition > instant)
            {
                return(new Transition(safeTransition, newOffset));
            }

            // We've got a transition earlier than we were asked for. Try next year.
            // Note that this will stil be within the FromYear/ToYear range, otherwise
            // safeLocal >= maxLocalInstant would have been triggered earlier.
            targetYear++;
            // Handle infinite transitions
            if (targetYear > GregorianYearMonthDayCalculator.MaxGregorianYear)
            {
                return(new Transition(Instant.AfterMaxValue, newOffset));
            }
            // It's fine for this to be "end of time", and it can't be "start of time" because we're at least finding a transition in -9997.
            safeTransition = YearOffset.GetOccurrenceForYear(targetYear).SafeMinus(ruleOffset);
            return(new Transition(safeTransition, newOffset));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns the last transition which occurs before or on the given instant.
        /// </summary>
        /// <param name="instant">The <see cref="Instant"/> lower bound for the next trasnition.</param>
        /// <param name="standardOffset">The <see cref="Offset"/> standard offset.</param>
        /// <param name="previousSavings">The <see cref="Offset"/> savings adjustment at the given Instant.</param>
        /// <returns>The previous transition, or null if there is no previous transition. The transition may be
        /// infinite, i.e. before the start of representable time.</returns>
        internal Transition?PreviousOrSame(Instant instant, Offset standardOffset, Offset previousSavings)
        {
            Offset ruleOffset = YearOffset.GetRuleOffset(standardOffset, previousSavings);
            Offset newOffset  = standardOffset + Savings;

            LocalInstant safeLocal = instant.SafePlus(ruleOffset);
            int          targetYear;

            if (safeLocal > maxLocalInstant)
            {
                // Asked for a transition before some point after our last year: crop to last year.
                targetYear = ToYear;
            }
            // Deliberately < here; "previous or same" means if safeLocal==minLocalInstant, we should compute it for this year.
            else if (safeLocal < minLocalInstant)
            {
                // Asked for a transition before our first one
                return(null);
            }
            else if (!safeLocal.IsValid)
            {
                if (safeLocal == LocalInstant.BeforeMinValue)
                {
                    // We've been asked to find the next transition before some point which is a valid instant, but is before the
                    // start of valid local time after applying the rule offset.  It's possible that the next transition *would*
                    // be representable as an instant (e.g. 1pm Dec 31st -9999 with an offset of -5) but it's reasonable to
                    // just return an infinite transition.
                    return(new Transition(Instant.BeforeMinValue, newOffset));
                }
                else
                {
                    // We've been asked to find the next transition before some point which is a valid instant, but is after the
                    // end of valid local time after applying the rule offset. For example, passing Instant.MaxValue for a rule which says
                    // "transition uses wall time, which is UTC+5". Proceed as if we'd been asked for something in 9999.
                    // I *think* that works...
                    targetYear = GregorianYearMonthDayCalculator.MaxGregorianYear;
                }
            }
            else
            {
                // Simple case: we were asked for a "normal" value in the range of years for which this recurrence is valid.
                targetYear = CalendarSystem.Iso.YearMonthDayCalculator.GetYear(safeLocal.DaysSinceEpoch, out int ignoredDayOfYear);
            }

            LocalInstant transition = YearOffset.GetOccurrenceForYear(targetYear);

            Instant safeTransition = transition.SafeMinus(ruleOffset);

            if (safeTransition <= instant)
            {
                return(new Transition(safeTransition, newOffset));
            }

            // We've got a transition later than we were asked for. Try next year.
            // Note that this will stil be within the FromYear/ToYear range, otherwise
            // safeLocal < minLocalInstant would have been triggered earlier.
            targetYear--;
            // Handle infinite transitions
            if (targetYear < GregorianYearMonthDayCalculator.MinGregorianYear)
            {
                return(new Transition(Instant.BeforeMinValue, newOffset));
            }
            // It's fine for this to be "start of time", and it can't be "end of time" because we're at latest finding a transition in 9998.
            safeTransition = YearOffset.GetOccurrenceForYear(targetYear).SafeMinus(ruleOffset);
            return(new Transition(safeTransition, newOffset));
        }