Example #1
0
        /// <summary>
        /// Parses a daylight savings rule and returns the Rule object.
        /// </summary>
        /// <remarks>
        /// # Rule    NAME    FROM    TO    TYPE    IN    ON    AT    SAVE    LETTER/S
        /// </remarks>
        /// <param name="tokens">The tokens to parse.</param>
        /// <returns>The Rule object.</returns>
        internal RuleLine ParseRule(Tokens tokens)
        {
            var name     = NextString(tokens, "GetName");
            int fromYear = NextYear(tokens, 0);

            // This basically doesn't happen these days, but if we have any recurrent rules
            // which start at the dawn of time, make them effective from 1900. This matches
            // zic behaviour in the only cases of this that we've seen, e.g. the systemv rules
            // prior to 2001a.
            if (fromYear == int.MinValue)
            {
                fromYear = 1900;
            }

            int toYear = NextYear(tokens, fromYear);

            if (toYear < fromYear)
            {
                throw new ArgumentException($"To year cannot be before the from year in a Rule: {toYear} < {fromYear}");
            }
            var type       = NextOptional(tokens, "Type");
            var yearOffset = ParseDateTimeOfYear(tokens, true);
            var savings    = NextOffset(tokens, "SaveMillis");
            var daylightSavingsIndicator = NextOptional(tokens, "LetterS");
            // The name of the zone recurrence is currently the name of the rule. Later (in ZoneRule.GetRecurrences)
            // it will be replaced with the formatted name. It's not ideal, but it avoids a lot of duplication.
            var recurrence = new ZoneRecurrence(name, savings, yearOffset, fromYear, toYear);

            return(new RuleLine(recurrence, daylightSavingsIndicator, type));
        }
Example #2
0
        public void ZoneRecurrenceToString()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var recurrence = new ZoneRecurrence("name", Offset.FromHours(1), yearOffset, 1900, 2000);

            Assert.AreEqual("name +01 ZoneYearOffset[mode:Utc monthOfYear:10 dayOfMonth:31 dayOfWeek:3 advance:True timeOfDay:00:00:00 addDay:False] [1900-2000]", recurrence.ToString());
        }
        public void Extremes()
        {
            ZoneRecurrence winter = new ZoneRecurrence("Winter", Offset.Zero,
                                                       new ZoneYearOffset(TransitionMode.Wall, 10, 5, 0, false, new LocalTime(2, 0)), int.MinValue, int.MaxValue);

            ZoneRecurrence summer = new ZoneRecurrence("Summer", Offset.FromHours(1),
                                                       new ZoneYearOffset(TransitionMode.Wall, 3, 10, 0, false, new LocalTime(1, 0)), int.MinValue, int.MaxValue);

            var zone = new StandardDaylightAlternatingMap(Offset.Zero, winter, summer);

            var firstSpring = Instant.FromUtc(-9998, 3, 10, 1, 0);
            var firstAutumn = Instant.FromUtc(-9998, 10, 5, 1, 0); // 1am UTC = 2am wall

            var lastSpring = Instant.FromUtc(9999, 3, 10, 1, 0);
            var lastAutumn = Instant.FromUtc(9999, 10, 5, 1, 0); // 1am UTC = 2am wall

            var dstOffset = Offset.FromHours(1);

            // Check both year -9998 and 9999, both the infinite interval and the next one in
            var firstWinter = new ZoneInterval("Winter", Instant.BeforeMinValue, firstSpring, Offset.Zero, Offset.Zero);
            var firstSummer = new ZoneInterval("Summer", firstSpring, firstAutumn, dstOffset, dstOffset);
            var lastSummer  = new ZoneInterval("Summer", lastSpring, lastAutumn, dstOffset, dstOffset);
            var lastWinter  = new ZoneInterval("Winter", lastAutumn, Instant.AfterMaxValue, Offset.Zero, Offset.Zero);

            Assert.AreEqual(firstWinter, zone.GetZoneInterval(Instant.MinValue));
            Assert.AreEqual(firstWinter, zone.GetZoneInterval(Instant.FromUtc(-9998, 2, 1, 0, 0)));
            Assert.AreEqual(firstSummer, zone.GetZoneInterval(firstSpring));
            Assert.AreEqual(firstSummer, zone.GetZoneInterval(Instant.FromUtc(-9998, 5, 1, 0, 0)));

            Assert.AreEqual(lastSummer, zone.GetZoneInterval(lastSpring));
            Assert.AreEqual(lastSummer, zone.GetZoneInterval(Instant.FromUtc(9999, 5, 1, 0, 0)));
            Assert.AreEqual(lastWinter, zone.GetZoneInterval(lastAutumn));
            Assert.AreEqual(lastWinter, zone.GetZoneInterval(Instant.FromUtc(9999, 11, 1, 0, 0)));
            Assert.AreEqual(lastWinter, zone.GetZoneInterval(Instant.MaxValue));
        }
        public void TestSerialization()
        {
            var dio        = DtzIoHelper.CreateNoStringPool();
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var expected   = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);

            dio.TestZoneRecurrence(expected);
        }
Example #5
0
        public void NextOrFail_Fail()
        {
            var afterRecurrenceEnd   = Instant.FromUtc(1980, 1, 1, 0, 0);
            var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
            var recurrence           = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);

            Assert.Throws <InvalidOperationException>(() => recurrence.NextOrFail(afterRecurrenceEnd, Offset.Zero, Offset.Zero));
        }
Example #6
0
 public void Equality()
 {
     var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
     var recurrence = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
     var actual = new RuleLine(recurrence, "D", null);
     var expected = new RuleLine(recurrence, "D", null);
     Assert.AreEqual(expected, actual);
 }
 public void Next_FirstYear()
 {
     var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, Offset.Zero);
     var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
     Transition? actual = recurrence.Next(Instant.UnixEpoch, Offset.Zero, Offset.Zero);
     Transition? expected = new Transition(new Instant(Instant.UnixEpoch.Ticks + (1 * TicksPerStandardYear)), Offset.Zero, Offset.Zero);
     Assert.AreEqual(expected, actual);
 }
 public void Next_BeforeFirstYear()
 {
     var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
     var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
     Transition? actual = recurrence.Next(Instant.MinValue, Offset.Zero, Offset.Zero);
     Transition? expected = new Transition(NodaConstants.UnixEpoch, Offset.Zero);
     Assert.AreEqual(expected, actual);
 }
Example #9
0
 public void WriteRead()
 {
     var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, Offset.Zero);
     var recurrence = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
     var actual = new ZoneRule(recurrence, "D");
     var expected = new ZoneRule(recurrence, "D");
     Assert.AreEqual(expected, actual);
 }
Example #10
0
 public void PreviousOrSame_AfterLastYear()
 {
     var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
     var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
     Transition? actual = recurrence.PreviousOrSame(Instant.MaxValue, Offset.Zero, Offset.Zero);
     Transition? expected = new Transition(Instant.FromUtc(1972, 1, 1, 0, 0), Offset.Zero);
     Assert.AreEqual(expected, actual);
 }
Example #11
0
 public void PreviousOrSame_LastYear()
 {
     var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
     var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
     Transition? actual = recurrence.PreviousOrSame(Instant.FromUtc(1971, 1, 1, 0, 0) - Duration.Epsilon, Offset.Zero, Offset.Zero);
     Transition? expected = new Transition(NodaConstants.UnixEpoch, Offset.Zero);
     Assert.AreEqual(expected, actual);
 }
Example #12
0
        public void PreviousOrSameOrFail_Fail()
        {
            var beforeRecurrenceStart = Instant.FromUtc(1960, 1, 1, 0, 0);
            var januaryFirstMidnight  = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
            var recurrence            = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);

            Assert.Throws <InvalidOperationException>(() => recurrence.PreviousOrSameOrFail(beforeRecurrenceStart, Offset.Zero, Offset.Zero));
        }
 public void RenameAppend()
 {
     var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, Offset.Zero);
     var old = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
     var actual = old.RenameAppend("-Summer");
     var expected = new ZoneRecurrence("bob-Summer", Offset.Zero, yearOffset, 1971, 2009);
     Assert.AreEqual(expected, actual);
 }
        public void PreviousOrSame_LastYear()
        {
            var        januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
            var        recurrence           = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
            Transition?actual   = recurrence.PreviousOrSame(Instant.FromUtc(1971, 1, 1, 0, 0) - Duration.Epsilon, Offset.Zero, Offset.Zero);
            Transition?expected = new Transition(NodaConstants.UnixEpoch, Offset.Zero);

            Assert.AreEqual(expected, actual);
        }
        public void PreviousOrSame_AfterLastYear()
        {
            var        januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
            var        recurrence           = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
            Transition?actual   = recurrence.PreviousOrSame(Instant.MaxValue, Offset.Zero, Offset.Zero);
            Transition?expected = new Transition(Instant.FromUtc(1972, 1, 1, 0, 0), Offset.Zero);

            Assert.AreEqual(expected, actual);
        }
        public void PreviousOrSame_IncludesGivenInstant()
        {
            var january10thMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 10, 0, true, LocalTime.Midnight);
            var recurrence          = new ZoneRecurrence("x", Offset.Zero, january10thMidnight, 2000, 3000);
            var transition          = Instant.FromUtc(2500, 1, 10, 0, 0);
            var next = recurrence.PreviousOrSame(transition, Offset.Zero, Offset.Zero);

            Assert.AreEqual(transition, next.Value.Instant);
        }
        public void Previous_LastYear()
        {
            var        januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
            var        recurrence           = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
            Transition?actual   = recurrence.Previous(new Instant(NodaConstants.UnixEpoch.Ticks + (1 * TicksPerStandardYear)), Offset.Zero, Offset.Zero);
            Transition?expected = new Transition(NodaConstants.UnixEpoch, Offset.Zero, Offset.Zero);

            Assert.AreEqual(expected, actual);
        }
Example #18
0
        public void Next_ExcludesGivenInstant()
        {
            var january10thMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 10, 0, true, LocalTime.Midnight);
            var recurrence          = new ZoneRecurrence("x", Offset.Zero, january10thMidnight, 2000, 3000);
            var transition          = Instant.FromUtc(2500, 1, 10, 0, 0);
            var next = recurrence.Next(transition, Offset.Zero, Offset.Zero);

            Assert.AreEqual(2501, next !.Value.Instant.InUtc().Year);
        }
        public void Previous_BeforeFirstYear_null()
        {
            var        januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
            var        recurrence           = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
            Transition?actual   = recurrence.Previous(NodaConstants.UnixEpoch - Duration.Epsilon, Offset.Zero, Offset.Zero);
            Transition?expected = null;

            Assert.AreEqual(expected, actual);
        }
Example #20
0
        public void Equality()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var recurrence = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
            var actual     = new RuleLine(recurrence, "D", null);
            var expected   = new RuleLine(recurrence, "D", null);

            Assert.AreEqual(expected, actual);
        }
        public void Next_BeforeFirstYear()
        {
            var        januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
            var        recurrence           = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
            Transition?actual   = recurrence.Next(Instant.MinValue, Offset.Zero, Offset.Zero);
            Transition?expected = new Transition(NodaConstants.UnixEpoch, Offset.Zero, Offset.Zero);

            Assert.AreEqual(expected, actual);
        }
Example #22
0
        public void TestZoneRecurrence(ZoneRecurrence expected)
        {
            Reset();
            expected.Write(Writer);
            var actual = ZoneRecurrence.Read(Reader);

            Assert.AreEqual(expected, actual);
            ioStream.AssertEndOfStream();
        }
 /// <summary>
 /// Adds a recurring daylight saving time rule.
 /// </summary>
 /// <param name="recurrence">The zone recurrence defining the recurrening savings.</param>
 /// <returns>This <see cref="DateTimeZoneBuilder"/> for chaining.</returns>
 public DateTimeZoneBuilder AddRecurringSavings(ZoneRecurrence recurrence)
 {
     Preconditions.CheckNotNull(recurrence, "recurrence");
     if (recurrence.FromYear <= recurrence.ToYear)
     {
         LastRuleSet.AddRule(recurrence);
     }
     return(this);
 }
Example #24
0
 public void Next_BeyondLastYear_null()
 {
     var afterRecurrenceEnd = Instant.FromUtc(1980, 1, 1, 0, 0);
     var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
     var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
     Transition? actual = recurrence.Next(afterRecurrenceEnd, Offset.Zero, Offset.Zero);
     Transition? expected = null;
     Assert.AreEqual(expected, actual);
 }
        public void Next_BeyondLastYear_null()
        {
            var        afterRecurrenceEnd   = Instant.FromUtc(1980, 1, 1, 0, 0);
            var        januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight);
            var        recurrence           = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
            Transition?actual   = recurrence.Next(afterRecurrenceEnd, Offset.Zero, Offset.Zero);
            Transition?expected = null;

            Assert.AreEqual(expected, actual);
        }
        public void IEquatable_Tests()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);

            var value        = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
            var equalValue   = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
            var unequalValue = new ZoneRecurrence("foo", Offset.Zero, yearOffset, 1971, 2009);

            TestHelper.TestEqualsClass(value, equalValue, unequalValue);
        }
        public void PreviousOrSame_OnFirstYear_null()
        {
            // Transition is on January 2nd, but we're asking for January 1st.
            var        januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 2, 0, true, LocalTime.Midnight);
            var        recurrence           = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
            Transition?actual   = recurrence.PreviousOrSame(NodaConstants.UnixEpoch, Offset.Zero, Offset.Zero);
            Transition?expected = null;

            Assert.AreEqual(expected, actual);
        }
Example #28
0
        public void FormatName_Slash_Daylight()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int) IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var recurrence = new ZoneRecurrence("ignored", Offset.FromHours(1), yearOffset, 1971, 2009);
            var rule = new RuleLine(recurrence, "!", null);
            var zone = GetZone("X/Y", Offset.FromHours(1));

            var zoneRecurrence = rule.GetRecurrences(zone).Single();
            Assert.AreEqual("Y", zoneRecurrence.Name);
        }
Example #29
0
        public void FormatName_PercentS()
        {
            // Note that the offset is irrelevant here - the "daylight saving indicator" is replaced either way.
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int) IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var recurrence = new ZoneRecurrence("ignored", Offset.Zero, yearOffset, 1971, 2009);
            var rule = new RuleLine(recurrence, "!", null);
            var zone = GetZone("X%sY", Offset.Zero);

            var zoneRecurrence = rule.GetRecurrences(zone).Single();
            Assert.AreEqual("X!Y", zoneRecurrence.Name);
        }
        public void December31st2400_MaxYear_UtcTransition()
        {
            // Each year, the transition is at the midnight at the *end* of December 31st...
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 12, 31, 0, true, LocalTime.Midnight, true);
            // ... and the recurrence is valid for the whole of time
            var recurrence = new ZoneRecurrence("awkward", Offset.FromHours(1), yearOffset, GregorianYearMonthDayCalculator.MinGregorianYear, GregorianYearMonthDayCalculator.MaxGregorianYear);

            var next = recurrence.Next(Instant.FromUtc(9999, 6, 1, 0, 0), Offset.Zero, Offset.Zero);

            Assert.AreEqual(Instant.AfterMaxValue, next.Value.Instant);
        }
Example #31
0
        public void FormatName_Slash_Daylight()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var recurrence = new ZoneRecurrence("ignored", Offset.FromHours(1), yearOffset, 1971, 2009);
            var rule       = new RuleLine(recurrence, "!", null);
            var zone       = GetZone("X/Y", Offset.FromHours(1));

            var zoneRecurrence = rule.GetRecurrences(zone).Single();

            Assert.AreEqual("Y", zoneRecurrence.Name);
        }
Example #32
0
        public void FormatName_PercentS()
        {
            // Note that the offset is irrelevant here - the "daylight saving indicator" is replaced either way.
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var recurrence = new ZoneRecurrence("ignored", Offset.Zero, yearOffset, 1971, 2009);
            var rule       = new RuleLine(recurrence, "!", null);
            var zone       = GetZone("X%sY", Offset.Zero);

            var zoneRecurrence = rule.GetRecurrences(zone).Single();

            Assert.AreEqual("X!Y", zoneRecurrence.Name);
        }
Example #33
0
        public void WithName()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var original   = new ZoneRecurrence("original", Offset.FromHours(1), yearOffset, 1900, 2000);
            var renamed    = original.WithName("renamed");

            Assert.AreEqual("renamed", renamed.Name);
            Assert.AreEqual(original.Savings, renamed.Savings);
            Assert.AreEqual(original.YearOffset, renamed.YearOffset);
            Assert.AreEqual(original.FromYear, renamed.FromYear);
            Assert.AreEqual(original.ToYear, renamed.ToYear);
        }
Example #34
0
        public void ForSingleYear()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var original   = new ZoneRecurrence("original", Offset.FromHours(1), yearOffset, 1900, 2000);
            var singleYear = original.ForSingleYear(2017);

            Assert.AreEqual(original.Name, singleYear.Name);
            Assert.AreEqual(original.Savings, singleYear.Savings);
            Assert.AreEqual(original.YearOffset, singleYear.YearOffset);
            Assert.AreEqual(2017, singleYear.FromYear);
            Assert.AreEqual(2017, singleYear.ToYear);
        }
        public void InvalidMap_SimultaneousTransition()
        {
            // Two recurrences with different savings, but which occur at the same instant in time every year.
            ZoneRecurrence r1 = new ZoneRecurrence("Recurrence1", Offset.Zero,
                                                   new ZoneYearOffset(TransitionMode.Utc, 10, 5, 0, false, new LocalTime(2, 0)), int.MinValue, int.MaxValue);

            ZoneRecurrence r2 = new ZoneRecurrence("Recurrence2", Offset.FromHours(1),
                                                   new ZoneYearOffset(TransitionMode.Utc, 10, 5, 0, false, new LocalTime(2, 0)), int.MinValue, int.MaxValue);

            var map = new StandardDaylightAlternatingMap(Offset.Zero, r1, r2);

            Assert.Throws <InvalidOperationException>(() => map.GetZoneInterval(Instant.FromUtc(2017, 8, 25, 0, 0, 0)));
        }
Example #36
0
            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));
            }
Example #37
0
        public void FormatName_PercentZ()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int) IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var recurrence = new ZoneRecurrence("Rule", Offset.FromHoursAndMinutes(5, 30), yearOffset, 1971, 2009);
            var rule = new RuleLine(recurrence, "D", null);
            
            var zoneRecurrence = rule.GetRecurrences(GetZone("X%zY", Offset.Zero)).Single();
            Assert.AreEqual("X+0530Y", zoneRecurrence.Name);

            zoneRecurrence = rule.GetRecurrences(GetZone("X%zY", Offset.FromHoursAndMinutes(0, 30))).Single();
            Assert.AreEqual("X+06Y", zoneRecurrence.Name);

            zoneRecurrence = rule.GetRecurrences(GetZone("X%zY", Offset.FromHoursAndMinutes(-6, -30))).Single();
            Assert.AreEqual("X-01Y", zoneRecurrence.Name);
        }
Example #38
0
        public void FormatName_PercentZ()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
            var recurrence = new ZoneRecurrence("Rule", Offset.FromHoursAndMinutes(5, 30), yearOffset, 1971, 2009);
            var rule       = new RuleLine(recurrence, "D", null);

            var zoneRecurrence = rule.GetRecurrences(GetZone("X%zY", Offset.Zero)).Single();

            Assert.AreEqual("X+0530Y", zoneRecurrence.Name);

            zoneRecurrence = rule.GetRecurrences(GetZone("X%zY", Offset.FromHoursAndMinutes(0, 30))).Single();
            Assert.AreEqual("X+06Y", zoneRecurrence.Name);

            zoneRecurrence = rule.GetRecurrences(GetZone("X%zY", Offset.FromHoursAndMinutes(-6, -30))).Single();
            Assert.AreEqual("X-01Y", zoneRecurrence.Name);
        }
        public void December31st2400_AskAtNanoBeforeLastTransition()
        {
            // The transition occurs after the end of the maximum
            // Each year, the transition is at the midnight at the *end* of December 31st...
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 12, 31, 0, true, LocalTime.Midnight, true);
            // ... and the recurrence is valid for the whole of time
            var recurrence = new ZoneRecurrence("awkward", Offset.FromHours(1), yearOffset, 1, 5000);

            // We can find the final transition
            var        finalTransition = Instant.FromUtc(5001, 1, 1, 0, 0);
            var        next            = recurrence.Next(finalTransition - Duration.Epsilon, Offset.Zero, Offset.Zero);
            Transition?expected        = new Transition(finalTransition, Offset.FromHours(1));

            Assert.AreEqual(expected, next);

            // But we correctly reject anything after that
            Assert.IsNull(recurrence.Next(finalTransition, Offset.Zero, Offset.Zero));
        }
Example #40
0
            /// <summary>
            /// If there are only two rules left and they are both infinite rules then a <see
            /// cref="DateTimeZone"/> implementation is returned that encapsulates those rules,
            /// otherwise null is returned.
            /// </summary>
            /// <param name="id">The id of the new <see cref="DateTimeZone"/>.</param>
            /// <returns>The new <see cref="DateTimeZone"/> or null.</returns>
            internal DateTimeZone BuildTailZone(String id)
            {
                if (rules.Count == 2)
                {
                    ZoneRecurrence startRule = rules[0];
                    ZoneRecurrence endRule   = rules[1];
                    if (startRule.IsInfinite && endRule.IsInfinite)
                    {
                        // With exactly two infinitely recurring rules left, a simple DaylightSavingsTimeZone can be
                        // formed.

                        // The order of rules can come in any order, and it doesn't really matter
                        // which rule was chosen the 'start' and which is chosen the 'end'. DaylightSavingsTimeZone
                        // works properly either way.
                        return(new DaylightSavingsDateTimeZone(id, ruleSet.StandardOffset, startRule, endRule));
                    }
                }
                return(null);
            }
Example #41
0
        /// <summary>
        ///   Parses a daylight savings rule and returns the Rule object.
        /// </summary>
        /// <remarks>
        ///   # Rule    NAME    FROM    TO    TYPE    IN    ON    AT    SAVE    LETTER/S
        /// </remarks>
        /// <param name="tokens">The tokens to parse.</param>
        /// <returns>The Rule object.</returns>
        internal ZoneRule ParseRule(Tokens tokens)
        {
            var name     = NextString(tokens, "GetName");
            int fromYear = NextYear(tokens, "FromYear", 0);
            int toYear   = NextYear(tokens, "ToYear", fromYear);

            if (toYear < fromYear)
            {
                throw new ArgumentException("To year cannot be before the from year in a Rule: " + toYear + " < " + fromYear);
            }
            /* string type = */
            NextOptional(tokens, "Type");
            var yearOffset = ParseDateTimeOfYear(tokens, true);
            var savings    = NextOffset(tokens, "SaveMillis");
            var letterS    = NextOptional(tokens, "LetterS");
            var recurrence = new ZoneRecurrence(name, savings, yearOffset, fromYear, toYear);

            return(new ZoneRule(recurrence, letterS));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="DaylightSavingsDateTimeZone"/> class.
 /// </summary>
 /// <remarks>
 /// At least one of the recurrences (it doesn't matter which) must be a "standard", i.e. not have any savings
 /// applied. The other may still not have any savings (e.g. for America/Resolute) or (for BCL compatibility) may
 /// even have negative daylight savings.
 /// </remarks>
 /// <param name="id">The id.</param>
 /// <param name="standardOffset">The standard offset.</param>
 /// <param name="startRecurrence">The start recurrence.</param>
 /// <param name="endRecurrence">The end recurrence.</param>
 internal DaylightSavingsDateTimeZone([NotNull] String id, Offset standardOffset, ZoneRecurrence startRecurrence, ZoneRecurrence endRecurrence)
     : base(id, false,
     standardOffset + Offset.Min(startRecurrence.Savings, endRecurrence.Savings),
     standardOffset + Offset.Max(startRecurrence.Savings, endRecurrence.Savings))
 {
     this.standardOffset = standardOffset;
     // Treat the recurrences as if they extended to the start of time.
     startRecurrence = startRecurrence.ToStartOfTime();
     endRecurrence = endRecurrence.ToStartOfTime();
     Preconditions.CheckArgument(startRecurrence.IsInfinite, nameof(startRecurrence), "Start recurrence must extend to the end of time");
     Preconditions.CheckArgument(endRecurrence.IsInfinite, nameof(endRecurrence), "End recurrence must extend to the end of time");
     var dst = startRecurrence;
     var standard = endRecurrence;
     if (startRecurrence.Savings == Offset.Zero)
     {
         dst = endRecurrence;
         standard = startRecurrence;
     }
     Preconditions.CheckArgument(standard.Savings == Offset.Zero, nameof(startRecurrence), "At least one recurrence must not have savings applied");
     dstRecurrence = dst;
     standardRecurrence = standard;
 }
Example #43
0
 public void PreviousOrSame_IncludesGivenInstant()
 {
     var january10thMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 10, 0, true, LocalTime.Midnight);
     var recurrence = new ZoneRecurrence("x", Offset.Zero, january10thMidnight, 2000, 3000);
     var transition = Instant.FromUtc(2500, 1, 10, 0, 0);
     var next = recurrence.PreviousOrSame(transition, Offset.Zero, Offset.Zero);
     Assert.AreEqual(transition, next.Value.Instant);
 }
        public void Extremes()
        {
            ZoneRecurrence winter = new ZoneRecurrence("Winter", Offset.Zero,
                new ZoneYearOffset(TransitionMode.Wall, 10, 5, 0, false, new LocalTime(2, 0)), int.MinValue, int.MaxValue);

            ZoneRecurrence summer = new ZoneRecurrence("Summer", Offset.FromHours(1),
                new ZoneYearOffset(TransitionMode.Wall, 3, 10, 0, false, new LocalTime(1, 0)), int.MinValue, int.MaxValue);

            var zone = new StandardDaylightAlternatingMap(Offset.Zero, winter, summer);

            var firstSpring = Instant.FromUtc(-9998, 3, 10, 1, 0);
            var firstAutumn = Instant.FromUtc(-9998, 10, 5, 1, 0); // 1am UTC = 2am wall

            var lastSpring = Instant.FromUtc(9999, 3, 10, 1, 0);
            var lastAutumn = Instant.FromUtc(9999, 10, 5, 1, 0); // 1am UTC = 2am wall

            var dstOffset = Offset.FromHours(1);

            // Check both year -9998 and 9999, both the infinite interval and the next one in
            var firstWinter = new ZoneInterval("Winter", Instant.BeforeMinValue, firstSpring, Offset.Zero, Offset.Zero);
            var firstSummer = new ZoneInterval("Summer", firstSpring, firstAutumn, dstOffset, dstOffset);
            var lastSummer = new ZoneInterval("Summer", lastSpring, lastAutumn, dstOffset, dstOffset);
            var lastWinter = new ZoneInterval("Winter", lastAutumn, Instant.AfterMaxValue, Offset.Zero, Offset.Zero);

            Assert.AreEqual(firstWinter, zone.GetZoneInterval(Instant.MinValue));
            Assert.AreEqual(firstWinter, zone.GetZoneInterval(Instant.FromUtc(-9998, 2, 1, 0, 0)));
            Assert.AreEqual(firstSummer, zone.GetZoneInterval(firstSpring));
            Assert.AreEqual(firstSummer, zone.GetZoneInterval(Instant.FromUtc(-9998, 5, 1, 0, 0)));

            Assert.AreEqual(lastSummer, zone.GetZoneInterval(lastSpring));
            Assert.AreEqual(lastSummer, zone.GetZoneInterval(Instant.FromUtc(9999, 5, 1, 0, 0)));
            Assert.AreEqual(lastWinter, zone.GetZoneInterval(lastAutumn));
            Assert.AreEqual(lastWinter, zone.GetZoneInterval(Instant.FromUtc(9999, 11, 1, 0, 0)));
            Assert.AreEqual(lastWinter, zone.GetZoneInterval(Instant.MaxValue));
        }
 internal static DaylightSavingsDateTimeZone Read([NotNull] IDateTimeZoneReader reader, [NotNull] string id)
 {
     Preconditions.CheckNotNull(reader, nameof(reader));
     Offset standardOffset = reader.ReadOffset();
     string standardName = reader.ReadString();
     ZoneYearOffset standardYearOffset = ZoneYearOffset.Read(reader);
     string daylightName = reader.ReadString();
     ZoneYearOffset daylightYearOffset = ZoneYearOffset.Read(reader);
     Offset savings = reader.ReadOffset();
     ZoneRecurrence standardRecurrence = new ZoneRecurrence(standardName, Offset.Zero, standardYearOffset, int.MinValue, int.MaxValue);
     ZoneRecurrence dstRecurrence = new ZoneRecurrence(daylightName, savings, daylightYearOffset, int.MinValue, int.MaxValue);
     return new DaylightSavingsDateTimeZone(id, standardOffset, standardRecurrence, dstRecurrence);
 }
Example #46
0
 public void TestZoneRecurrence(ZoneRecurrence expected)
 {
     Reset();
     expected.Write(Writer);
     var actual = ZoneRecurrence.Read(Reader);
     Assert.AreEqual(expected, actual);
     ioStream.AssertEndOfStream();
 }
 /// <summary>
 ///   Parses a daylight savings rule and returns the Rule object.
 /// </summary>
 /// <remarks>
 ///   # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 /// </remarks>
 /// <param name="tokens">The tokens to parse.</param>
 /// <returns>The Rule object.</returns>
 internal ZoneRule ParseRule(Tokens tokens)
 {
     var name = NextString(tokens, "GetName");
     int fromYear = NextYear(tokens, "FromYear", 0);
     int toYear = NextYear(tokens, "ToYear", fromYear);
     if (toYear < fromYear)
     {
         throw new ArgumentException("To year cannot be before the from year in a Rule: " + toYear + " < " + fromYear);
     }
     /* string type = */
     NextOptional(tokens, "Type");
     var yearOffset = ParseDateTimeOfYear(tokens);
     var savings = NextOffset(tokens, "SaveMillis");
     var letterS = NextOptional(tokens, "LetterS");
     var recurrence = new ZoneRecurrence(name, savings, yearOffset, fromYear, toYear);
     return new ZoneRule(recurrence, letterS);
 }
Example #48
0
        public void December31st2400_AskAtNanoBeforeLastTransition()
        {
            // The transition occurs after the end of the maximum
            // Each year, the transition is at the midnight at the *end* of December 31st...
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 12, 31, 0, true, LocalTime.Midnight, true);
            // ... and the recurrence is valid for the whole of time
            var recurrence = new ZoneRecurrence("awkward", Offset.FromHours(1), yearOffset, 1, 5000);

            // We can find the final transition
            var finalTransition = Instant.FromUtc(5001, 1, 1, 0, 0);
            var next = recurrence.Next(finalTransition - Duration.Epsilon, Offset.Zero, Offset.Zero);
            Transition? expected = new Transition(finalTransition, Offset.FromHours(1));
            Assert.AreEqual(expected, next);

            // But we correctly reject anything after that
            Assert.IsNull(recurrence.Next(finalTransition, Offset.Zero, Offset.Zero));
        }
 public void Test()
 {
     var dio = new DtzIoHelper("ZoneRecurrence");
     var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, Offset.Zero);
     var expected = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
     dio.TestZoneRecurrence(expected);
 }
Example #50
0
        public void December31st2400_MaxYear_UtcTransition()
        {
            // Each year, the transition is at the midnight at the *end* of December 31st...
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 12, 31, 0, true, LocalTime.Midnight, true);
            // ... and the recurrence is valid for the whole of time
            var recurrence = new ZoneRecurrence("awkward", Offset.FromHours(1), yearOffset, GregorianYearMonthDayCalculator.MinGregorianYear, GregorianYearMonthDayCalculator.MaxGregorianYear);

            var next = recurrence.Next(Instant.FromUtc(9999, 6, 1, 0, 0), Offset.Zero, Offset.Zero);
            Assert.AreEqual(Instant.AfterMaxValue, next.Value.Instant);
        }
 public void Previous_BeforeFirstYear_null()
 {
     var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, Offset.Zero);
     var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
     Transition? actual = recurrence.Previous(Instant.UnixEpoch - Duration.One, Offset.Zero, Offset.Zero);
     Transition? expected = null;
     Assert.AreEqual(expected, actual);
 }
        public void Extremes()
        {
            ZoneRecurrence winter = new ZoneRecurrence("Winter", Offset.Zero,
                new ZoneYearOffset(TransitionMode.Wall, 10, 5, 0, false, new LocalTime(2, 0)), int.MinValue, int.MaxValue);

            ZoneRecurrence summer = new ZoneRecurrence("Summer", Offset.FromHours(1),
                new ZoneYearOffset(TransitionMode.Wall, 3, 10, 0, false, new LocalTime(1, 0)), int.MinValue, int.MaxValue);

            var zone = new DaylightSavingsDateTimeZone("infinite", Offset.Zero, winter, summer);

            var firstSpring = Instant.FromUtc(-9998, 3, 10, 1, 0);
            var firstAutumn = Instant.FromUtc(-9998, 10, 5, 1, 0); // 1am UTC = 2am wall

            var lastSpring = Instant.FromUtc(9999, 3, 10, 1, 0);
            var lastAutumn = Instant.FromUtc(9999, 10, 5, 1, 0); // 1am UTC = 2am wall

            var dstOffset = Offset.FromHours(1);

            // Check both year -9998 and 9999, both the infinite interval and the next one in
            var firstWinter = new ZoneInterval("Winter", Instant.BeforeMinValue, firstSpring, Offset.Zero, Offset.Zero);
            var firstSummer = new ZoneInterval("Summer", firstSpring, firstAutumn, dstOffset, dstOffset);
            var lastSummer = new ZoneInterval("Summer", lastSpring, lastAutumn, dstOffset, dstOffset);
            var lastWinter = new ZoneInterval("Winter", lastAutumn, Instant.AfterMaxValue, Offset.Zero, Offset.Zero);

            Assert.AreEqual(firstWinter, zone.GetZoneInterval(Instant.MinValue));
            Assert.AreEqual(firstWinter, zone.GetZoneInterval(Instant.FromUtc(-9998, 2, 1, 0, 0)));
            Assert.AreEqual(firstSummer, zone.GetZoneInterval(firstSpring));
            Assert.AreEqual(firstSummer, zone.GetZoneInterval(Instant.FromUtc(-9998, 5, 1, 0, 0)));

            Assert.AreEqual(lastSummer, zone.GetZoneInterval(lastSpring));
            Assert.AreEqual(lastSummer, zone.GetZoneInterval(Instant.FromUtc(9999, 5, 1, 0, 0)));
            Assert.AreEqual(lastWinter, zone.GetZoneInterval(lastAutumn));
            Assert.AreEqual(lastWinter, zone.GetZoneInterval(Instant.FromUtc(9999, 11, 1, 0, 0)));
            Assert.AreEqual(lastWinter, zone.GetZoneInterval(Instant.MaxValue));

            // And just for kicks, let's check we can get them all with GetZoneIntervals.
            IEnumerable<ZoneInterval> intervals = zone.GetZoneIntervals(new Interval(null, null)).ToList();
            Assert.AreEqual(firstWinter, intervals.First());
            Assert.AreEqual(firstSummer, intervals.Skip(1).First());
            Assert.AreEqual(lastSummer, intervals.Reverse().Skip(1).First());
            Assert.AreEqual(lastWinter, intervals.Last());
        }
 /// <summary>
 /// Returns the transition occurring strictly after the specified instant. The <paramref name="recurrence"/>
 /// parameter will be populated with the recurrence the transition goes *from*.
 /// </summary>
 /// <param name="instant">The instant after which to consider transitions.</param>
 /// <param name="recurrence">Receives the savings offset for the transition.</param>
 private Transition NextTransition(Instant instant, out ZoneRecurrence recurrence)
 {
     // Both recurrences are infinite, so they'll both have previous transitions (possibly at int.MinValue).
     Transition dstTransition = dstRecurrence.NextOrFail(instant, standardOffset, Offset.Zero);
     Transition standardTransition = standardRecurrence.NextOrFail(instant, standardOffset, dstRecurrence.Savings);
     var standardTransitionInstant = standardTransition.Instant;
     var dstTransitionInstant = dstTransition.Instant;
     if (standardTransitionInstant < dstTransitionInstant)
     {
         // Next transition is from DST to standard.
         recurrence = dstRecurrence;
         return standardTransition;
     }
     else if (standardTransitionInstant > dstTransitionInstant)
     {
         // Next transition is from standard to DST.
         recurrence = standardRecurrence;
         return dstTransition;
     }
     else
     {
         // Okay, the transitions happen at the same time. If they're not at infinity, we're stumped.
         if (standardTransitionInstant.IsValid)
         {
             throw new InvalidOperationException("Zone recurrence rules have identical transitions. This time zone is broken.");
         }
         // Okay, the two transitions must be to the end of time. Find which recurrence has the later *previous* transition...
         var previousDstTransition = dstRecurrence.PreviousOrSameOrFail(instant, standardOffset, Offset.Zero);
         var previousStandardTransition = standardRecurrence.PreviousOrSameOrFail(instant, standardOffset, dstRecurrence.Savings);
         // No point in checking for equality here... they can't go back from the end of time to the start...
         if (previousDstTransition.Instant > previousStandardTransition.Instant)
         {
             // The previous transition is from standard to DST. Therefore the next one is from DST to standard.
             recurrence = dstRecurrence;
             return standardTransition;
         }
         else
         {
             // The previous transition is from standard to DST. Therefore the next one is from DST to standard.
             recurrence = standardRecurrence;
             return dstTransition;
         }
     }
 }
Example #54
0
 public void PreviousOrSame_OnFirstYear_null()
 {
     // Transition is on January 2nd, but we're asking for January 1st.
     var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 2, 0, true, LocalTime.Midnight);
     var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972);
     Transition? actual = recurrence.PreviousOrSame(NodaConstants.UnixEpoch, Offset.Zero, Offset.Zero);
     Transition? expected = null;
     Assert.AreEqual(expected, actual);
 }
Example #55
0
        /// <summary>
        /// Parses a daylight savings rule and returns the Rule object.
        /// </summary>
        /// <remarks>
        /// # Rule    NAME    FROM    TO    TYPE    IN    ON    AT    SAVE    LETTER/S
        /// </remarks>
        /// <param name="tokens">The tokens to parse.</param>
        /// <returns>The Rule object.</returns>
        internal RuleLine ParseRule(Tokens tokens)
        {
            var name = NextString(tokens, "GetName");
            int fromYear = NextYear(tokens, 0);

            // This basically doesn't happen these days, but if we have any recurrent rules
            // which start at the dawn of time, make them effective from 1900. This matches
            // zic behaviour in the only cases of this that we've seen, e.g. the systemv rules
            // prior to 2001a.
            if (fromYear == int.MinValue)
            { 
                fromYear = 1900;
            }

            int toYear = NextYear(tokens, fromYear);
            if (toYear < fromYear)
            {
                throw new ArgumentException($"To year cannot be before the from year in a Rule: {toYear} < {fromYear}");
            }
            var type = NextOptional(tokens, "Type");
            var yearOffset = ParseDateTimeOfYear(tokens, true);
            var savings = NextOffset(tokens, "SaveMillis");
            var daylightSavingsIndicator = NextOptional(tokens, "LetterS");
            // The name of the zone recurrence is currently the name of the rule. Later (in ZoneRule.GetRecurrences)
            // it will be replaced with the formatted name. It's not ideal, but it avoids a lot of duplication.
            var recurrence = new ZoneRecurrence(name, savings, yearOffset, fromYear, toYear);
            return new RuleLine(recurrence, daylightSavingsIndicator, type);
        }
Example #56
0
 public void TestSerialization()
 {
     var dio = DtzIoHelper.CreateNoStringPool();
     var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);
     var expected = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
     dio.TestZoneRecurrence(expected);
 }
            internal BclAdjustmentRule(TimeZoneInfo zone, TimeZoneInfo.AdjustmentRule rule)
            {
                // With .NET 4.6, adjustment rules can have their own standard offsets, allowing
                // a much more reasonable set of time zone data. Unfortunately, this isn't directly
                // exposed, but we can detect it by just finding the UTC offset for an arbitrary
                // time within the rule - the start, in this case - and then take account of the
                // possibility of that being in daylight saving time. Fortunately, we only need
                // to do this during the setup.
                var ruleStandardOffset = zone.GetUtcOffset(rule.DateStart);
                if (zone.IsDaylightSavingTime(rule.DateStart))
                {
                    ruleStandardOffset -= rule.DaylightDelta;
                }
                StandardOffset = ruleStandardOffset.ToOffset();

                // Although the rule may have its own standard offset, the start/end is still determined
                // using the zone's standard offset.
                var zoneStandardOffset = zone.BaseUtcOffset.ToOffset();

                // Note: this extends back from DateTime.MinValue to start of time, even though the BCL can represent
                // as far back as 1AD. This is in the *spirit* of a rule which goes back that far.
                Start = rule.DateStart == DateTime.MinValue ? Instant.BeforeMinValue : rule.DateStart.ToLocalDateTime().WithOffset(zoneStandardOffset).ToInstant();
                // The end instant (exclusive) is the end of the given date, so we need to add a day.
                End = rule.DateEnd == MaxDate ? Instant.AfterMaxValue : rule.DateEnd.ToLocalDateTime().PlusDays(1).WithOffset(zoneStandardOffset).ToInstant();
                Savings = rule.DaylightDelta.ToOffset();

                // Some rules have DST start/end of "January 1st", to indicate that they're just in standard time. This is important
                // for rules which have a standard offset which is different to the standard offset of the zone itself.
                if (IsStandardOffsetOnlyRule(rule))
                {
                    PartialMap = PartialZoneIntervalMap.ForZoneInterval(zone.StandardName, Start, End, StandardOffset, Offset.Zero);
                }
                else
                {
                    var daylightRecurrence = new ZoneRecurrence(zone.DaylightName, Savings, ConvertTransition(rule.DaylightTransitionStart), int.MinValue, int.MaxValue);
                    var standardRecurrence = new ZoneRecurrence(zone.StandardName, Offset.Zero, ConvertTransition(rule.DaylightTransitionEnd), int.MinValue, int.MaxValue);
                    var recurringMap = new DaylightSavingsDateTimeZone("ignored", StandardOffset, standardRecurrence, daylightRecurrence);
                    PartialMap = new PartialZoneIntervalMap(Start, End, recurringMap);
                }
            }
Example #58
0
        public void IEquatable_Tests()
        {
            var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, LocalTime.Midnight);

            var value = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
            var equalValue = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
            var unequalValue = new ZoneRecurrence("foo", Offset.Zero, yearOffset, 1971, 2009);

            TestHelper.TestEqualsClass(value, equalValue, unequalValue);
        }
 /// <summary>
 /// Adds a recurring daylight saving time rule.
 /// </summary>
 /// <param name="recurrence">The zone recurrence defining the recurrening savings.</param>
 /// <returns>This <see cref="DateTimeZoneBuilder"/> for chaining.</returns> 
 public DateTimeZoneBuilder AddRecurringSavings(ZoneRecurrence recurrence)
 {
     Preconditions.CheckNotNull(recurrence, "recurrence");
     if (recurrence.FromYear <= recurrence.ToYear)
     {
         LastRuleSet.AddRule(recurrence);
     }
     return this;
 }
 public void RenameAppend_nullSuffix()
 {
     var yearOffset = new ZoneYearOffset(TransitionMode.Utc, 10, 31, (int)IsoDayOfWeek.Wednesday, true, Offset.Zero);
     var old = new ZoneRecurrence("bob", Offset.Zero, yearOffset, 1971, 2009);
     Assert.Throws(typeof(ArgumentNullException), () => old.RenameAppend(null), "Null suffix");
 }