// From http://stackoverflow.com/questions/15211052/what-is-the-system-timezoneinfo-isdaylightsavingtime-equivalent-in-nodatime
        // Thanks to Matt Johnson
        public static bool IsDaylightSavingsTime(ZonedDateTime zonedDateTime)
        {
            Instant      instant      = zonedDateTime.ToInstant();
            ZoneInterval zoneInterval = zonedDateTime.Zone.GetZoneInterval(instant);

            return(zoneInterval.Savings != Offset.Zero);
        }
Пример #2
0
        public void FakeDaylightSavingTime()
        {
            // .NET Core on Unix loses data from rules provided to CreateCustomTimeZone :(
            // (It assumes the rules have been created from tzif files, which isn't the case here.)
            Ignore.When(TestHelper.IsRunningOnDotNetCoreUnix, ".NET Core on Unix mangles custom time zones");

            // Linux time zones on Mono can have a strange situation with a "0 savings" adjustment rule to represent
            // "we want to change standard time but we can't".
            // See https://github.com/nodatime/nodatime/issues/746
            // Normally the odd rule would only be in place for a year, but it's simplest to just make it all the time.
            // We go into daylight savings at midday on March 10th, and out again at midday on September 25.

            // We should be able to use DateTime.MaxValue for dateEnd, but not in .NET 4.5 apparently.
            var rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(DateTime.MinValue, new DateTime(9999, 12, 31), TimeSpan.Zero,
                                                                        TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, 12, 0, 0), 3, 10),
                                                                        TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, 12, 0, 0), 9, 25));
            var bclZone        = TimeZoneInfo.CreateCustomTimeZone("Nasty", TimeSpan.FromHours(4), "Display", "Standard", "Daylight", new[] { rule });
            var nodaZone       = BclDateTimeZone.FromTimeZoneInfo(bclZone);
            var winterInterval = nodaZone.GetZoneInterval(Instant.FromUtc(2017, 2, 1, 0, 0));
            var summerInterval = nodaZone.GetZoneInterval(Instant.FromUtc(2017, 6, 1, 0, 0));

            var expectedWinter = new ZoneInterval("Standard", Instant.FromUtc(2016, 9, 25, 8, 0), Instant.FromUtc(2017, 3, 10, 8, 0), Offset.FromHours(4), Offset.Zero);
            var expectedSummer = new ZoneInterval("Daylight", Instant.FromUtc(2017, 3, 10, 8, 0), Instant.FromUtc(2017, 9, 25, 8, 0), Offset.FromHours(4), Offset.FromHours(1));

            Assert.AreEqual(expectedWinter, winterInterval);
            Assert.AreEqual(expectedSummer, summerInterval);
        }
Пример #3
0
 public void GetPeriod_AfterLastTransition()
 {
     var may1981 = DateTimeZone.Utc.AtExactly(new LocalDateTime(1981, 5, 1, 0, 0, 1)).ToInstant();
     var actual = Algiers.GetZoneInterval(may1981);
     var expected = new ZoneInterval("CET", new Instant(3575232000000000L), Instant.MaxValue, Offset.FromMilliseconds(NodaConstants.MillisecondsPerHour), Offset.Zero);
     Assert.AreEqual(expected, actual);
 }
Пример #4
0
 public void GetPeriod_BeforeLast()
 {
     Instant april1981 = Instant.FromUtc(1981, 4, 1, 0, 0);
     var actual = Algiers.GetZoneInterval(april1981);
     var expected = new ZoneInterval("WET", Instant.FromUnixTimeTicks(3418020000000000L), Instant.FromUnixTimeTicks(3575232000000000L), Offset.Zero, Offset.Zero);
     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 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));
        }
Пример #6
0
 public void GetPeriod_BeforeLast()
 {
     Instant april1981 = Instant.FromUtc(1981, 4, 1, 0, 0);
     var actual = Algiers.GetZoneInterval(april1981);
     var expected = new ZoneInterval("WET", Instant.FromUnixTimeTicks(3418020000000000L), Instant.FromUnixTimeTicks(3575232000000000L), Offset.Zero, Offset.Zero);
     Assert.AreEqual(expected, actual);
 }
Пример #7
0
 public void GetPeriod_AfterLastTransition()
 {
     var may1981 = DateTimeZone.Utc.AtStrictly(new LocalDateTime(1981, 5, 1, 0, 0, 1)).ToInstant();
     var actual = Algiers.GetZoneInterval(may1981);
     var expected = new ZoneInterval("CET", Instant.FromUnixTimeTicks(3575232000000000L), null, Offset.FromSeconds(NodaConstants.SecondsPerHour), Offset.Zero);
     Assert.AreEqual(expected, actual);
 }
        /// <summary>
        /// Dumps the contents of a provider to a writer. This is used in both unit tests and TzdbCompiler, so we can validate
        /// that changes to time zone code don't change behaviour. It's not expected to be exposed publicly; this used to
        /// be in NodaTime.CheckZones, but that didn't really prove its worth. It's currently very fix in format and options;
        /// we can make it more flexible later if we want.
        /// </summary>
        internal static void Dump([NotNull] this IDateTimeZoneProvider provider, [NotNull] TextWriter writer)
        {
            Preconditions.CheckNotNull(provider, nameof(provider));
            Preconditions.CheckNotNull(writer, nameof(writer));
            writer.WriteLine("TZDB version: {0}", provider.VersionId);
            foreach (var id in provider.Ids)
            {
                var zone = provider[id];
                writer.WriteLine($"Zone: {zone.Id}");
                var          start         = Instant.FromUtc(1800, 1, 1, 0, 0);
                var          end           = Instant.FromUtc(2100, 1, 1, 0, 0);
                ZoneInterval lastDisplayed = null;

                foreach (var interval in zone.GetZoneIntervals(start, end))
                {
                    writer.WriteLine(interval);
                    lastDisplayed = interval;
                }

                // This will never be null; every interval has at least one zone interval.
                if (lastDisplayed.HasEnd)
                {
                    writer.WriteLine("...");
                    writer.WriteLine(zone.GetZoneInterval(Instant.MaxValue));
                }
                writer.WriteLine();
            }
        }
Пример #9
0
        public void IsoLocalStartAndEnd_Infinite()
        {
            var interval = new ZoneInterval("All time", null, null, Offset.Zero, Offset.Zero);

            Assert.Throws <InvalidOperationException>(() => interval.IsoLocalStart.ToString());
            Assert.Throws <InvalidOperationException>(() => interval.IsoLocalEnd.ToString());
        }
Пример #10
0
 public void GetPeriod_AfterLastTransition()
 {
     var may1981 = DateTimeZone.Utc.AtStrictly(new LocalDateTime(1981, 5, 1, 0, 0, 1)).ToInstant();
     var actual = Algiers.GetZoneInterval(may1981);
     var expected = new ZoneInterval("CET", Instant.FromUnixTimeTicks(3575232000000000L), null, Offset.FromSeconds(NodaConstants.SecondsPerHour), Offset.Zero);
     Assert.AreEqual(expected, actual);
 }
 /// <summary>
 /// Creates a zone with a single transition between two offsets.
 /// </summary>
 /// <param name="transitionPoint">The transition point as an <see cref="Instant"/>.</param>
 /// <param name="offsetBefore">The offset of local time from UTC before the transition.</param>
 /// <param name="offsetAfter">The offset of local time from UTC before the transition.</param>
 /// <param name="id">ID for the newly created time zone.</param>
 public SingleTransitionDateTimeZone(Instant transitionPoint, Offset offsetBefore, Offset offsetAfter, string id)
     : base(id, false, Offset.Min(offsetBefore, offsetAfter), Offset.Max(offsetBefore, offsetAfter))
 {
     EarlyInterval = new ZoneInterval(id + "-Early", null, transitionPoint,
         offsetBefore, Offset.Zero);
     LateInterval = new ZoneInterval(id + "-Late", transitionPoint, null,
         offsetAfter, Offset.Zero);
 }
Пример #12
0
 /// <summary>
 /// Creates a zone with a single transition between two offsets.
 /// </summary>
 /// <param name="transitionPoint">The transition point as an <see cref="Instant"/>.</param>
 /// <param name="offsetBefore">The offset of local time from UTC before the transition.</param>
 /// <param name="offsetAfter">The offset of local time from UTC before the transition.</param>
 public SingleTransitionZone(Instant transitionPoint, Offset offsetBefore, Offset offsetAfter)
     : base("Single", false, Offset.Min(offsetBefore, offsetAfter), Offset.Max(offsetBefore, offsetAfter))
 {
     earlyInterval = new ZoneInterval("Single-Early", Instant.MinValue, transitionPoint,
         offsetBefore, Offset.Zero);
     lateInterval = new ZoneInterval("Single-Late", transitionPoint, Instant.MaxValue,
         offsetAfter, Offset.Zero);
 }
Пример #13
0
        private void CheckMapping(LocalDateTime localDateTime, ZoneInterval earlyInterval, ZoneInterval lateInterval, int count)
        {
            var mapping = TestZone.MapLocal(localDateTime);

            Assert.AreEqual(earlyInterval, mapping.EarlyInterval);
            Assert.AreEqual(lateInterval, mapping.LateInterval);
            Assert.AreEqual(count, mapping.Count);
        }
Пример #14
0
        public void IsoLocalStartAndEnd_OutOfRange()
        {
            var interval = new ZoneInterval("All time", Instant.MinValue, null, Offset.FromHours(-1), Offset.Zero);

            Assert.Throws <OverflowException>(() => interval.IsoLocalStart.ToString());
            interval = new ZoneInterval("All time", null, Instant.MaxValue, Offset.FromHours(11), Offset.Zero);
            Assert.Throws <OverflowException>(() => interval.IsoLocalEnd.ToString());
        }
Пример #15
0
 /// <summary>
 /// Creates a zone with a single transition between two offsets.
 /// </summary>
 /// <param name="transitionPoint">The transition point as an <see cref="Instant"/>.</param>
 /// <param name="offsetBefore">The offset of local time from UTC before the transition.</param>
 /// <param name="offsetAfter">The offset of local time from UTC before the transition.</param>
 /// <param name="id">ID for the newly created time zone.</param>
 public SingleTransitionDateTimeZone(Instant transitionPoint, Offset offsetBefore, Offset offsetAfter, string id)
     : base(id, false, Offset.Min(offsetBefore, offsetAfter), Offset.Max(offsetBefore, offsetAfter))
 {
     EarlyInterval = new ZoneInterval(id + "-Early", null, transitionPoint,
                                      offsetBefore, Offset.Zero);
     LateInterval = new ZoneInterval(id + "-Late", transitionPoint, null,
                                     offsetAfter, Offset.Zero);
 }
Пример #16
0
 public void Contains_LocalInstant_WholeOfTime()
 {
     ZoneInterval interval = new ZoneInterval("All Time", Instant.BeforeMinValue, Instant.AfterMaxValue,
         Offset.FromHours(9), Offset.FromHours(1));
     Assert.IsTrue(interval.Contains(SampleStart.Plus(Offset.Zero)));
     Assert.IsTrue(interval.Contains(Instant.MinValue.Plus(Offset.Zero)));
     Assert.IsTrue(interval.Contains(Instant.MaxValue.Plus(Offset.Zero)));
 }
Пример #17
0
 public void Contains_Instant_WholeOfTime_ViaSpecialInstants()
 {
     ZoneInterval interval = new ZoneInterval("All Time", Instant.BeforeMinValue, Instant.AfterMaxValue,
         Offset.FromHours(9), Offset.FromHours(1));
     Assert.IsTrue(interval.Contains(SampleStart));
     Assert.IsTrue(interval.Contains(Instant.MinValue));
     Assert.IsTrue(interval.Contains(Instant.MaxValue));
 }
Пример #18
0
 public void Contains_Instant_WholeOfTime_ViaNullity()
 {
     ZoneInterval interval = new ZoneInterval("All Time", null, null,
         Offset.FromHours(9), Offset.FromHours(1));
     Assert.IsTrue(interval.Contains(SampleStart));
     Assert.IsTrue(interval.Contains(Instant.MinValue));
     Assert.IsTrue(interval.Contains(Instant.MaxValue));
 }
Пример #19
0
        public void Contains_LocalInstant_WholeOfTime()
        {
            ZoneInterval interval = new ZoneInterval("All Time", Instant.MinValue, Instant.MaxValue,
                                                     Offset.FromHours(9), Offset.FromHours(1));

            Assert.IsTrue(interval.Contains(SampleStart.Plus(Offset.Zero)));
            Assert.IsTrue(interval.Contains(LocalInstant.MinValue));
            Assert.IsTrue(interval.Contains(LocalInstant.MaxValue));
        }
Пример #20
0
        public void Contains_Instant_WholeOfTime_ViaSpecialInstants()
        {
            ZoneInterval interval = new ZoneInterval("All Time", Instant.BeforeMinValue, Instant.AfterMaxValue,
                                                     Offset.FromHours(9), Offset.FromHours(1));

            Assert.IsTrue(interval.Contains(SampleStart));
            Assert.IsTrue(interval.Contains(Instant.MinValue));
            Assert.IsTrue(interval.Contains(Instant.MaxValue));
        }
Пример #21
0
        public void Contains_Instant_WholeOfTime_ViaNullity()
        {
            ZoneInterval interval = new ZoneInterval("All Time", null, null,
                                                     Offset.FromHours(9), Offset.FromHours(1));

            Assert.IsTrue(interval.Contains(SampleStart));
            Assert.IsTrue(interval.Contains(Instant.MinValue));
            Assert.IsTrue(interval.Contains(Instant.MaxValue));
        }
Пример #22
0
        public void ZoneInterval()
        {
            DateTimeZone london   = DateTimeZoneProviders.Tzdb["Europe/London"];
            ZoneInterval interval = london.GetZoneInterval(Instant.FromUtc(2010, 6, 19, 0, 0));

            Assert.AreEqual("BST", interval.Name);
            Assert.AreEqual(Instant.FromUtc(2010, 3, 28, 1, 0), interval.Start);
            Assert.AreEqual(Instant.FromUtc(2010, 10, 31, 1, 0), interval.End);
            Assert.AreEqual(Offset.FromHours(1), interval.WallOffset);
            Assert.AreEqual(Offset.FromHours(1), interval.Savings);
        }
Пример #23
0
            public IntervalRecurrencePattern(ZoneInterval interval)
            {
                Frequency = FrequencyType.Yearly;
                ByMonth.Add(interval.IsoLocalStart.Month);

                var date    = interval.IsoLocalStart.ToDateTimeUnspecified();
                var weekday = date.DayOfWeek;
                var num     = DateUtil.WeekOfMonth(date);

                ByDay.Add(num != 5 ? new WeekDay(weekday, num) : new WeekDay(weekday, -1));
            }
Пример #24
0
 public void Contains_OutsideLocalInstantange()
 {
     ZoneInterval veryEarly = new ZoneInterval("Very early", Instant.BeforeMinValue, Instant.MinValue + Duration.FromHours(8), Offset.FromHours(-9), Offset.Zero);
     ZoneInterval veryLate = new ZoneInterval("Very late", Instant.MaxValue - Duration.FromHours(8), Instant.AfterMaxValue, Offset.FromHours(9), Offset.Zero);
     // The instants are contained...
     Assert.IsTrue(veryEarly.Contains(Instant.MinValue + Duration.FromHours(4)));
     Assert.IsTrue(veryLate.Contains(Instant.MaxValue - Duration.FromHours(4)));
     // But there are no valid local instants
     Assert.IsFalse(veryEarly.Contains(Instant.MinValue.Plus(Offset.Zero)));
     Assert.IsFalse(veryLate.Contains(Instant.MaxValue.Plus(Offset.Zero)));
 }
Пример #25
0
        public static bool IsStandardTime(Instant instant, DateTimeZone zone)
        {
            ZoneInterval zoneInterval = zone.GetZoneInterval(instant);
            Offset       offset       = zoneInterval.Savings;

            if (offset.Seconds > 0)
            {
                return(false);
            }

            return(true);
        }
    static ZonedDateTime ShiftForward(
        LocalDateTime local,
        DateTimeZone zone,
        ZoneInterval intervalBefore,
        ZoneInterval intervalAfter)
    {
        var instant = new OffsetDateTime(local, intervalBefore.WallOffset)
                      .WithOffset(intervalAfter.WallOffset)
                      .ToInstant();

        return(new ZonedDateTime(instant, zone));
    }
 /// <summary>
 /// Validates that all the periods before the tail zone make sense. We have to start at the beginning of time,
 /// and then have adjoining periods. This is only called in the constructors.
 /// </summary>
 /// <remarks>This is only called from the constructors, but is internal to make it easier to test.</remarks>
 /// <exception cref="ArgumentException">The periods specified are invalid.</exception>
 internal static void ValidatePeriods(ZoneInterval[] periods, IZoneIntervalMap tailZone)
 {
     Preconditions.CheckArgument(periods.Length > 0, nameof(periods), "No periods specified in precalculated time zone");
     Preconditions.CheckArgument(!periods[0].HasStart, nameof(periods), "Periods in precalculated time zone must start with the beginning of time");
     for (int i = 0; i < periods.Length - 1; i++)
     {
         // Safe to use End here: there can't be a period *after* an endless one. Likewise it's safe to use Start on the next 
         // period, as there can't be a period *before* one which goes back to the start of time.
         Preconditions.CheckArgument(periods[i].End == periods[i + 1].Start, nameof(periods), "Non-adjoining ZoneIntervals for precalculated time zone");
     }
     Preconditions.CheckArgument(tailZone != null || periods[periods.Length - 1].RawEnd == Instant.AfterMaxValue, nameof(tailZone), "Null tail zone given but periods don't cover all of time");
 }
Пример #28
0
        public void Contains_OutsideLocalInstantange()
        {
            ZoneInterval veryEarly = new ZoneInterval("Very early", Instant.BeforeMinValue, Instant.MinValue + Duration.FromHours(8), Offset.FromHours(-9), Offset.Zero);
            ZoneInterval veryLate  = new ZoneInterval("Very late", Instant.MaxValue - Duration.FromHours(8), Instant.AfterMaxValue, Offset.FromHours(9), Offset.Zero);

            // The instants are contained...
            Assert.IsTrue(veryEarly.Contains(Instant.MinValue + Duration.FromHours(4)));
            Assert.IsTrue(veryLate.Contains(Instant.MaxValue - Duration.FromHours(4)));
            // But there are no valid local instants
            Assert.IsFalse(veryEarly.Contains(Instant.MinValue.Plus(Offset.Zero)));
            Assert.IsFalse(veryLate.Contains(Instant.MaxValue.Plus(Offset.Zero)));
        }
Пример #29
0
        /// <summary>
        /// Generates a POSIX time zone string from an IANA time zone name, for the given year.
        /// </summary>
        /// <param name="timeZoneName">The IANA time zone name.</param>
        /// <param name="year">The reference year.</param>
        /// <returns>A POSIX time zone string.</returns>
        public static string FromIanaTimeZoneName(string timeZoneName, int year)
        {
            DateTimeZone tz = DateTimeZoneProviders.Tzdb[timeZoneName];

            ZonedDateTime jan = new LocalDate(year, 1, 1).AtStartOfDayInZone(tz);
            ZonedDateTime jul = new LocalDate(year, 7, 1).AtStartOfDayInZone(tz);

            ZoneInterval janInterval = tz.GetZoneInterval(jan.ToInstant());
            ZoneInterval julInterval = tz.GetZoneInterval(jul.ToInstant());

            ZoneInterval stdInterval = janInterval.Savings == Offset.Zero
                ? janInterval
                : julInterval;

            ZoneInterval dltInterval = janInterval.Savings != Offset.Zero
                ? janInterval
                : julInterval.Savings != Offset.Zero
                    ? julInterval
                    : null;

            var sb = new StringBuilder();

            string stdAbbreviation = GetPosixAbbreviation(stdInterval.Name);

            sb.Append(stdAbbreviation);

            string stdOffsetString = GetPosixOffsetString(stdInterval.WallOffset);

            sb.Append(stdOffsetString);

            if (dltInterval != null)
            {
                string dltAbbreviation = GetPosixAbbreviation(dltInterval.Name);
                sb.Append(dltAbbreviation);

                if (dltInterval.Savings != Offset.FromHours(1))
                {
                    string dltOffsetString = GetPosixOffsetString(dltInterval.WallOffset);
                    sb.Append(dltOffsetString);
                }

                string stdTransitionString = GetPosixTransitionString(stdInterval, tz);
                sb.Append("," + stdTransitionString);

                string dltTransitionString = GetPosixTransitionString(dltInterval, tz);
                sb.Append("," + dltTransitionString);
            }

            return(sb.ToString());
        }
Пример #30
0
 /// <summary>
 /// Gets the zone interval's start time in DateTimeKind.Utc ticks
 /// </summary>
 private static long GetDateTimeUtcTicks(ZoneInterval zoneInterval)
 {
     // can't convert these values directly to date times, so just shortcut these here
     // we set the min value to one since the logic in the ctor will decrement this value to
     // determine the last instant BEFORE the discontinuity
     if (zoneInterval.Start == Instant.MinValue)
     {
         return(1);
     }
     if (zoneInterval.Start == Instant.MaxValue)
     {
         return(DateTime.MaxValue.Ticks);
     }
     return(zoneInterval.Start.ToDateTimeUtc().Ticks);
 }
Пример #31
0
        private static PrecalculatedDateTimeZone CreatePrecalculatedDateTimeZone(string id, IList <ZoneTransition> transitions,
                                                                                 Instant tailZoneStart, DateTimeZone tailZone)
        {
            // Convert the transitions to intervals
            int size      = transitions.Count;
            var intervals = new ZoneInterval[size];

            for (int i = 0; i < size; i++)
            {
                var transition = transitions[i];
                var endInstant = i == size - 1 ? tailZoneStart : transitions[i + 1].Instant;
                intervals[i] = new ZoneInterval(transition.Name, transition.Instant, endInstant, transition.WallOffset, transition.Savings);
            }
            return(new PrecalculatedDateTimeZone(id, intervals, tailZone));
        }
 internal PrecalculatedDateTimeZone([NotNull] string id, [NotNull] ZoneInterval[] intervals, IZoneIntervalMapWithMinMax tailZone)
     : base(id, false,
            ComputeOffset(intervals, tailZone, Offset.Min),
            ComputeOffset(intervals, tailZone, Offset.Max))
 {
     this.tailZone = tailZone;
     this.periods = intervals;
     this.tailZone = tailZone;
     this.tailZoneStart = intervals[intervals.Length - 1].RawEnd; // We want this to be AfterMaxValue for tail-less zones.
     if (tailZone != null)
     {
         // Cache a "clamped" zone interval for use at the start of the tail zone.
         firstTailZoneInterval = tailZone.GetZoneInterval(tailZoneStart).WithStart(tailZoneStart);
     }
     ValidatePeriods(intervals, tailZone);
 }
Пример #33
0
        private ZoneInterval GetIntervalAfterGap(LocalInstant localInstant)
        {
            Instant      guess         = new Instant(localInstant.Ticks);
            ZoneInterval guessInterval = GetZoneInterval(guess);

            // If the local interval occurs before the zone interval we're looking at starts,
            // it's the one we're looking for. Otherwise, we need to find the next interval.
            if (localInstant.Minus(guessInterval.WallOffset) < guessInterval.Start)
            {
                return(guessInterval);
            }
            else
            {
                return(GetZoneInterval(guessInterval.End));
            }
        }
Пример #34
0
        private static string GetPosixTransitionString(ZoneInterval interval, DateTimeZone tz)
        {
            if (!interval.HasEnd)
            {
                return("J365/25");
            }

            LocalDateTime transition           = interval.IsoLocalEnd;
            int           transitionOccurrence = (transition.Day - 1) / 7 + 1;

            // return "last occurrence" (5) when appropriate
            if (transitionOccurrence == 4)
            {
                for (var i = 1; i <= 7; i++)
                {
                    var          futureInstant  = interval.IsoLocalEnd.PlusYears(i).InZoneLeniently(tz).ToInstant();
                    ZoneInterval futureInterval = tz.GetZoneInterval(futureInstant);
                    int          occurrence     = (futureInterval.IsoLocalEnd.Day - 1) / 7 + 1;
                    if (occurrence < 4)
                    {
                        transitionOccurrence = 4;
                        break;
                    }

                    if (occurrence == 5)
                    {
                        transitionOccurrence = 5;
                    }
                }
            }

            var datePart = $"M{transition.Month}.{transitionOccurrence}.{(int)transition.DayOfWeek.ToDayOfWeek()}";

            if (transition.TimeOfDay == new LocalTime(2, 0))
            {
                return(datePart);
            }
            if (transition.Minute == 0 && transition.Second == 0)
            {
                return($"{datePart}/{transition.Hour}");
            }
            if (transition.Second == 0)
            {
                return($"{datePart}/{transition.ToString("H:mm", CultureInfo.InvariantCulture)}");
            }
            return($"{datePart}/{transition.ToString("H:mm:ss", CultureInfo.InvariantCulture)}");
        }
Пример #35
0
        internal ZonedDateTime ResolveLocal(LocalDateTime localDateTime,
                                            [Trusted][NotNull] AmbiguousTimeResolver ambiguousResolver,
                                            [Trusted][NotNull] SkippedTimeResolver skippedResolver)
        {
            Preconditions.DebugCheckNotNull(ambiguousResolver, nameof(ambiguousResolver));
            Preconditions.DebugCheckNotNull(skippedResolver, nameof(skippedResolver));
            LocalInstant localInstant = localDateTime.ToLocalInstant();
            Instant      firstGuess   = localInstant.MinusZeroOffset();
            ZoneInterval interval     = GetZoneInterval(firstGuess);

            // Most of the time we'll go into here... the local instant and the instant
            // are close enough that we've found the right instant.
            if (interval.Contains(localInstant))
            {
                ZonedDateTime guessZoned = new ZonedDateTime(localDateTime.WithOffset(interval.WallOffset), this);
                ZoneInterval  earlier    = GetEarlierMatchingInterval(interval, localInstant);
                if (earlier != null)
                {
                    ZonedDateTime earlierZoned = new ZonedDateTime(localDateTime.WithOffset(earlier.WallOffset), this);
                    return(ambiguousResolver(earlierZoned, guessZoned));
                }
                ZoneInterval later = GetLaterMatchingInterval(interval, localInstant);
                if (later != null)
                {
                    ZonedDateTime laterZoned = new ZonedDateTime(localDateTime.WithOffset(later.WallOffset), this);
                    return(ambiguousResolver(guessZoned, laterZoned));
                }
                return(guessZoned);
            }
            else
            {
                // Our first guess was wrong. Either we need to change interval by one (either direction)
                // or we're in a gap.
                ZoneInterval earlier = GetEarlierMatchingInterval(interval, localInstant);
                if (earlier != null)
                {
                    return(new ZonedDateTime(localDateTime.WithOffset(earlier.WallOffset), this));
                }
                ZoneInterval later = GetLaterMatchingInterval(interval, localInstant);
                if (later != null)
                {
                    return(new ZonedDateTime(localDateTime.WithOffset(later.WallOffset), this));
                }
                return(skippedResolver(localDateTime, this, GetIntervalBeforeGap(localInstant), GetIntervalAfterGap(localInstant)));
            }
        }
Пример #36
0
        private ZoneInterval GetIntervalAfterGap(LocalInstant localInstant)
        {
            Instant      guess         = localInstant.MinusZeroOffset();
            ZoneInterval guessInterval = GetZoneInterval(guess);

            // If the local interval occurs before the zone interval we're looking at starts,
            // it's the one we're looking for. Otherwise, we need to find the next interval.
            if (localInstant.Minus(guessInterval.WallOffset) < guessInterval.RawStart)
            {
                return(guessInterval);
            }
            else
            {
                // Will definitely be valid - there can't be a gap after an infinite interval.
                return(GetZoneInterval(guessInterval.End));
            }
        }
Пример #37
0
        private ZoneInterval GetIntervalBeforeGap(LocalInstant localInstant)
        {
            Instant      guess         = localInstant.MinusZeroOffset();
            ZoneInterval guessInterval = GetZoneInterval(guess);

            // If the local interval occurs before the zone interval we're looking at starts,
            // we need to find the earlier one; otherwise this interval must come after the gap, and
            // it's therefore the one we want.
            if (localInstant.Minus(guessInterval.WallOffset) < guessInterval.RawStart)
            {
                return(GetZoneInterval(guessInterval.Start - Duration.Epsilon));
            }
            else
            {
                return(guessInterval);
            }
        }
Пример #38
0
        /// <summary>
        /// Creates a new <see cref="BclDateTimeZone" /> from a <see cref="TimeZoneInfo"/> from the Base Class Library.
        /// </summary>
        /// <param name="bclZone">The original time zone to take information from.</param>
        /// <returns>A <see cref="BclDateTimeZone"/> wrapping the given <c>TimeZoneInfo</c>.</returns>
        public static BclDateTimeZone FromTimeZoneInfo([NotNull] TimeZoneInfo bclZone)
        {
            Preconditions.CheckNotNull(bclZone, nameof(bclZone));
            Offset standardOffset = bclZone.BaseUtcOffset.ToOffset();
            var rules = bclZone.GetAdjustmentRules();
            if (!bclZone.SupportsDaylightSavingTime || rules.Length == 0)
            {
                var fixedInterval = new ZoneInterval(bclZone.StandardName, Instant.BeforeMinValue, Instant.AfterMaxValue, standardOffset, Offset.Zero);
                return new BclDateTimeZone(bclZone, standardOffset, standardOffset, new SingleZoneIntervalMap(fixedInterval));
            }

            BclAdjustmentRule[] convertedRules = Array.ConvertAll(rules, rule => new BclAdjustmentRule(bclZone, rule));
            Offset minRuleOffset = convertedRules.Aggregate(Offset.MaxValue, (min, rule) => Offset.Min(min, rule.Savings + rule.StandardOffset));
            Offset maxRuleOffset = convertedRules.Aggregate(Offset.MinValue, (min, rule) => Offset.Max(min, rule.Savings + rule.StandardOffset));

            IZoneIntervalMap uncachedMap = BuildMap(convertedRules, standardOffset, bclZone.StandardName);
            IZoneIntervalMap cachedMap = CachingZoneIntervalMap.CacheMap(uncachedMap, CachingZoneIntervalMap.CacheType.Hashtable);
            return new BclDateTimeZone(bclZone, Offset.Min(standardOffset, minRuleOffset), Offset.Max(standardOffset, maxRuleOffset), cachedMap);
        }
        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());
        }
Пример #40
0
        private static IEnumerable <ZoneInterval> GetBoundIntervals(DateTimeZone zone, Instant start, Instant end)
        {
            var intervals = zone.GetZoneIntervals(start, end).ToList();

            var first = intervals.First();

            if (!first.HasStart || first.Start < start)
            {
                intervals[0] = new ZoneInterval(first.Name, start, first.HasEnd ? first.End : (Instant?)null, first.WallOffset, first.Savings);
            }

            var last = intervals.Last();

            if (!last.HasEnd || last.End > end)
            {
                intervals[intervals.Count - 1] = new ZoneInterval(last.Name, last.HasStart ? last.Start : (Instant?)null, end, last.WallOffset, last.Savings);
            }

            return(intervals);
        }
Пример #41
0
        /// <summary>
        /// Returns the next interval after this one, if it contains the given local instant, or null otherwise.
        /// </summary>
        private ZoneInterval GetLaterMatchingInterval(ZoneInterval interval, LocalInstant localInstant)
        {
            // Micro-optimization to avoid fetching interval.End multiple times. Seems
            // to give a performance improvement on x86 at least...
            Instant intervalEnd = interval.End;

            if (intervalEnd == Instant.MaxValue)
            {
                return(null);
            }
            if (intervalEnd.Ticks + minOffsetTicks <= localInstant.Ticks)
            {
                ZoneInterval candidate = GetZoneInterval(intervalEnd);
                if (candidate.Contains(localInstant))
                {
                    return(candidate);
                }
            }
            return(null);
        }
Пример #42
0
        private static IEnumerable <ZoneInterval> GetBoundIntervals(DateTimeZone zone, Instant start, Instant end)
        {
            var intervals = zone.GetZoneIntervals(start, end).ToList();

            var first = intervals.First();

            if (first.Start == Instant.MinValue || first.Start < start)
            {
                intervals[0] = new ZoneInterval(first.Name, start, first.End, first.WallOffset, first.Savings);
            }

            var last = intervals.Last();

            if (last.End == Instant.MaxValue || last.End > end)
            {
                intervals[intervals.Count - 1] = new ZoneInterval(last.Name, last.Start, end, last.WallOffset, last.Savings);
            }

            return(intervals);
        }
 /// <summary>
 /// Builds a PartialZoneIntervalMap wrapping the given zone interval, taking its start and end as the start and end of
 /// the portion of the time line handled by the partial map.
 /// </summary>
 internal static PartialZoneIntervalMap ForZoneInterval(ZoneInterval interval) =>
     new PartialZoneIntervalMap(interval.RawStart, interval.RawEnd, new SingleZoneIntervalMap(interval));
        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 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());
        }
Пример #46
0
 /// <summary>
 /// Returns the next interval after this one, if it contains the given local instant, or null otherwise.
 /// </summary>
 private ZoneInterval GetLaterMatchingInterval(ZoneInterval interval, LocalInstant localInstant)
 {
     // Micro-optimization to avoid fetching interval.End multiple times. Seems
     // to give a performance improvement on x86 at least...
     Instant intervalEnd = interval.End;
     if (intervalEnd == Instant.MaxValue)
     {
         return null;
     }
     if (intervalEnd.Ticks + minOffsetTicks <= localInstant.Ticks)
     {
         ZoneInterval candidate = GetZoneInterval(intervalEnd);
         if (candidate.Contains(localInstant))
         {
             return candidate;
         }
     }
     return null;
 }
Пример #47
0
 private ZonedDateTime BuildZonedDateTime(ZoneInterval interval) =>
     new ZonedDateTime(LocalDateTime.WithOffset(interval.WallOffset), Zone);
Пример #48
0
 public void IsoLocalStartAndEnd_OutOfRange()
 {
     var interval = new ZoneInterval("All time", Instant.MinValue, null, Offset.FromHours(-1), Offset.Zero);
     Assert.Throws<OverflowException>(() => interval.IsoLocalStart.ToString());
     interval = new ZoneInterval("All time", null, Instant.MaxValue, Offset.FromHours(11), Offset.Zero);
     Assert.Throws<OverflowException>(() => interval.IsoLocalEnd.ToString());
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="HashCacheNode"/> class.
 /// </summary>
 /// <param name="interval">The zone interval.</param>
 /// <param name="period"></param>
 /// <param name="previous">The previous <see cref="HashCacheNode"/> node.</param>
 private HashCacheNode(ZoneInterval interval, int period, HashCacheNode previous)
 {
     this.Period = period;
     this.Interval = interval;
     this.Previous = previous;
 }
Пример #50
0
 private static PrecalculatedDateTimeZone CreatePrecalculatedDateTimeZone(string id, IList<ZoneTransition> transitions,
     Instant tailZoneStart, DateTimeZone tailZone)
 {
     // Convert the transitions to intervals
     int size = transitions.Count;
     var intervals = new ZoneInterval[size];
     for (int i = 0; i < size; i++)
     {
         var transition = transitions[i];
         var endInstant = i == size - 1 ? tailZoneStart : transitions[i + 1].Instant;
         intervals[i] = new ZoneInterval(transition.Name, transition.Instant, endInstant, transition.WallOffset, transition.Savings);
     }
     return new PrecalculatedDateTimeZone(id, intervals, tailZone);
 }
Пример #51
0
 internal SingleZoneIntervalMap(ZoneInterval interval)
 {
     this.interval = interval;
 }
 private void CheckMapping(LocalDateTime localDateTime, ZoneInterval earlyInterval, ZoneInterval lateInterval, int count)
 {
     var mapping = TestZone.MapLocal(localDateTime);
     Assert.AreEqual(earlyInterval, mapping.EarlyInterval);
     Assert.AreEqual(lateInterval, mapping.LateInterval);
     Assert.AreEqual(count, mapping.Count);
 }
Пример #53
0
        /// <summary>
        /// Gets the zone interval's start time in DateTimeKind.Utc ticks
        /// </summary>
        private static long GetDateTimeUtcTicks(ZoneInterval zoneInterval)
        {
            // can't convert these values directly to date times, so just shortcut these here
            // we set the min value to one since the logic in the ctor will decrement this value to
            // determine the last instant BEFORE the discontinuity
            if (zoneInterval.Start == Instant.MinValue) return 1;
            if (zoneInterval.Start == Instant.MaxValue) return DateTime.MaxValue.Ticks;

            return zoneInterval.Start.ToDateTimeUtc().Ticks;
        }
Пример #54
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FixedDateTimeZone"/> class.
 /// </summary>
 /// <remarks>The name (for the <see cref="ZoneInterval"/>) is deemed to be the same as the ID.</remarks>
 /// <param name="id">The id.</param>
 /// <param name="offset">The offset.</param>
 /// <param name="name">The name to use in the sole <see cref="ZoneInterval"/> in this zone.</param>
 public FixedDateTimeZone([NotNull] string id, Offset offset, [NotNull] string name) : base(id, true, offset, offset)
 {
     interval = new ZoneInterval(name, Instant.BeforeMinValue, Instant.AfterMaxValue, offset, Offset.Zero);
 }
 /// <summary>
 /// Reads a time zone from the specified reader.
 /// </summary>
 /// <param name="reader">The reader.</param>
 /// <param name="id">The id.</param>
 /// <returns>The time zone.</returns>
 internal static DateTimeZone Read([Trusted] [NotNull] IDateTimeZoneReader reader, [Trusted] [NotNull] string id)
 {
     Preconditions.DebugCheckNotNull(reader, nameof(reader));
     Preconditions.DebugCheckNotNull(id, nameof(id));
     int size = reader.ReadCount();
     var periods = new ZoneInterval[size];
     // It's not entirely clear why we don't just assume that the first zone interval always starts at Instant.BeforeMinValue
     // (given that we check that later) but we don't... and changing that now could cause compatibility issues.
     var start = reader.ReadZoneIntervalTransition(null);
     for (int i = 0; i < size; i++)
     {
         var name = reader.ReadString();
         var offset = reader.ReadOffset();
         var savings = reader.ReadOffset();
         var nextStart = reader.ReadZoneIntervalTransition(start);
         periods[i] = new ZoneInterval(name, start, nextStart, offset, savings);
         start = nextStart;
     }
     var tailZone = reader.ReadByte() == 1 ? StandardDaylightAlternatingMap.Read(reader) : null;
     return new PrecalculatedDateTimeZone(id, periods, tailZone);
 }
Пример #56
0
 internal SkippedMappingResult(ZoneInterval beforeTransition, ZoneInterval afterTransition) : base(ResultType.Skipped)
 {
     this.beforeTransition = beforeTransition;
     this.afterTransition = afterTransition;
 }
Пример #57
0
 public void IsoLocalStartAndEnd_Infinite()
 {
     var interval = new ZoneInterval("All time", null, null, Offset.Zero, Offset.Zero);
     Assert.Throws<InvalidOperationException>(() => interval.IsoLocalStart.ToString());
     Assert.Throws<InvalidOperationException>(() => interval.IsoLocalEnd.ToString());
 }
 private void CheckMapping(ZoneLocalMapping mapping, ZoneInterval earlyInterval, ZoneInterval lateInterval, int count)
 {
     Assert.AreEqual(earlyInterval, mapping.EarlyInterval);
     Assert.AreEqual(lateInterval, mapping.LateInterval);
     Assert.AreEqual(count, mapping.Count);
 }
Пример #59
0
 internal static ZoneLocalMapping SkippedResult(ZoneInterval beforeTransition, ZoneInterval afterTransition)
 {
     return new SkippedMappingResult(beforeTransition, afterTransition);
 }
Пример #60
0
 /// <summary>
 /// Returns the interval before this one, if it contains the given local instant, or null otherwise.
 /// </summary>
 private ZoneInterval GetEarlierMatchingInterval(ZoneInterval interval, LocalInstant localInstant)
 {
     // Micro-optimization to avoid fetching interval.Start multiple times. Seems
     // to give a performance improvement on x86 at least...
     Instant intervalStart = interval.Start;
     if (intervalStart == Instant.MinValue)
     {
         return null;
     }
     // If the tick before this interval started *could* map to a later local instant, let's
     // get the interval and check whether it actually includes the one we want.
     Instant endOfPrevious = intervalStart;
     if (endOfPrevious.Ticks + maxOffsetTicks > localInstant.Ticks)
     {
         ZoneInterval candidate = GetZoneInterval(endOfPrevious - Duration.One);
         if (candidate.Contains(localInstant))
         {
             return candidate;
         }
     }
     return null;
 }