/// <summary> /// Returns the given instant adjusted one year forward taking into account leap years and other /// adjustments like day of week. /// </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.</returns> internal Transition?Next(Instant instant, Offset standardOffset, Offset previousSavings) { CalendarSystem calendar = CalendarSystem.Iso; Offset wallOffset = standardOffset + previousSavings; int year = instant == Instant.MinValue ? Int32.MinValue : calendar.GetYear(instant.Plus(wallOffset)); if (year < fromYear) { // First advance instant to start of from year. instant = calendar.GetLocalInstant(fromYear, 1, 1, 0, 0).Minus(wallOffset); // Back off one tick to account for next recurrence being exactly at the beginning // of the year. instant = instant - Duration.Epsilon; } Instant next = yearOffset.Next(instant, standardOffset, previousSavings); if (next >= instant) { year = calendar.GetYear(next.Plus(wallOffset)); if (year > toYear) { return(null); } } return(new Transition(next, wallOffset, standardOffset + Savings)); }
/// <summary> /// Returns the given instant adjusted one year backward taking into account leap years and other /// adjustments like day of week. /// </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.</returns> internal Transition?Previous(Instant instant, Offset standardOffset, Offset previousSavings) { CalendarSystem calendar = CalendarSystem.Iso; Offset wallOffset = standardOffset + previousSavings; int year = instant == Instant.MaxValue ? Int32.MaxValue : calendar.GetYear(instant.Plus(wallOffset)); if (year > toYear) { // First pull instant back to the start of the year after toYear instant = calendar.GetLocalInstant(toYear + 1, 1, 1, 0, 0).Minus(wallOffset); } Instant previous = yearOffset.Previous(instant, standardOffset, previousSavings); if (previous <= instant) { year = calendar.GetYear(previous.Plus(wallOffset)); if (year < fromYear) { return(null); } } return(new Transition(previous, wallOffset, standardOffset + Savings)); }
private ZoneTransition GetNext(Instant nextInstant) { // Find next matching rule. ZoneRecurrence nextRule = null; Instant nextTicks = Instant.MaxValue; for (int i = 0; i < rules.Count; i++) { ZoneRecurrence rule = rules[i]; Transition? nextTransition = rule.Next(nextInstant, ruleSet.StandardOffset, savings); Instant? next = nextTransition == null ? (Instant?)null : nextTransition.Value.Instant; if (!next.HasValue || next.Value <= nextInstant) { rules.RemoveAt(i); i--; continue; } // Even if next is same as previous next, choose the rule in order for more // recently added rules to override. if (next.Value <= nextTicks) { // Found a better match. nextRule = rule; nextTicks = next.Value; } } if (nextRule == null) { return(null); } // Stop precalculating if year reaches some arbitrary limit. We can cheat in the // conversion because it is an approximation anyway. if (calendar.GetYear(nextTicks.Plus(Offset.Zero)) >= YearLimit) { return(null); } // Check if upper limit reached or passed. if (ruleSet.upperYear < Int32.MaxValue) { Instant upperTicks = ruleSet.upperYearOffset.MakeInstant(ruleSet.upperYear, ruleSet.StandardOffset, savings); if (nextTicks >= upperTicks) { // At or after upper limit. return(null); } } return(new ZoneTransition(nextTicks, nextRule.Name, ruleSet.StandardOffset, nextRule.Savings)); }