示例#1
0
        public void DisplayName(NamedWrapper <TimeZoneInfo> windowsZoneWrapper)
        {
            var windowsZone = windowsZoneWrapper.Value;
            var nodaZone    = BclDateTimeZone.FromTimeZoneInfo(windowsZone);

            Assert.AreEqual(windowsZone.DisplayName, nodaZone.DisplayName);
        }
示例#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 static DateTime AsUtc(this IDateTime dateTime)
        {
            if (dateTime.IsUniversalTime)
            {
                return(DateTime.SpecifyKind(dateTime.Value, DateTimeKind.Utc));
            }
            if (!string.IsNullOrEmpty(dateTime.TZID))
            {
                var zone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(dateTime.TZID);
                if (zone == null)
                {
                    var mappedTzid = TimeZoneMapper.WindowsToIanaOrNull(dateTime.TZID);
                    zone = mappedTzid != null
                        ? DateTimeZoneProviders.Tzdb.GetZoneOrNull(mappedTzid)
                        : BclDateTimeZone.ForSystemDefault();
                }

                if (zone != null)
                {
                    var localDateTime = LocalDateTime.FromDateTime(dateTime.Value);
                    var zonedDateTime = zone.AtLeniently(localDateTime);
                    var utcDateTime   = zonedDateTime.ToDateTimeUtc();
                    return(utcDateTime);
                }
            }

            // fallback
            return(DateTime.SpecifyKind(dateTime.Value, DateTimeKind.Local).ToUniversalTime());
        }
示例#4
0
        public void DateTimeMinValueStartRuleExtendsToBeginningOfTime()
        {
            // .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.)
            // See https://github.com/dotnet/corefx/issues/29912
            Ignore.When(TestHelper.IsRunningOnDotNetCoreUnix, ".NET Core on Unix mangles custom time zones");

            var rules = new[]
            {
                // Rule for the whole of time, with DST of 1 hour commencing on March 1st
                // and ending on September 1st.
                TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(
                    DateTime.MinValue, DateTime.MaxValue.Date, TimeSpan.FromHours(1),
                    TimeZoneInfo.TransitionTime.CreateFixedDateRule(DateTime.MinValue, 3, 1),
                    TimeZoneInfo.TransitionTime.CreateFixedDateRule(DateTime.MinValue, 9, 1))
            };
            var bclZone = TimeZoneInfo.CreateCustomTimeZone("custom", baseUtcOffset: TimeSpan.Zero,
                                                            displayName: "DisplayName", standardDisplayName: "Standard",
                                                            daylightDisplayName: "Daylight",
                                                            adjustmentRules: rules);
            var nodaZone = BclDateTimeZone.FromTimeZoneInfo(bclZone);

            // Standard time in February BC 101
            Assert.AreEqual(Offset.Zero, nodaZone.GetUtcOffset(Instant.FromUtc(-100, 2, 1, 0, 0)));
            // Daylight time in July BC 101
            Assert.AreEqual(Offset.FromHours(1), nodaZone.GetUtcOffset(Instant.FromUtc(-100, 7, 1, 0, 0)));
            // Standard time in October BC 101
            Assert.AreEqual(Offset.Zero, nodaZone.GetUtcOffset(Instant.FromUtc(-100, 10, 1, 0, 0)));
        }
        static void Main(string[] args)
        {
            // Arizona without daylight saving time (TZ: America/Phoenix)
            var mstWithoutDstTz = TimeZoneInfo.FindSystemTimeZoneById("US Mountain Standard Time");

            // Arizona with daylight saving time (TZ: America/Shiprock)
            var mstWithDstTz = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time");

            // NodaTime BclDateTimeZone for Arizona without daylight saving time
            var mstWithoutDstNodaTz = BclDateTimeZone.FromTimeZoneInfo(mstWithoutDstTz);

            // NodaTime BclDateTimeZone for Arizona with daylight saving time
            var mstWithDstNodaTz = BclDateTimeZone.FromTimeZoneInfo(mstWithDstTz);

            // January 1, 2017, 15:00, local winter date
            var localWinterDate = new LocalDateTime(2017, 01, 01, 15, 00);

            // NodaTime ZonedDateTime for Arizona without daylight saving time: January 1, 2017, 15:00
            var winterTimeWithoutDst = mstWithoutDstNodaTz.AtStrictly(localWinterDate);

            // NodaTime ZonedDateTime for Arizona with daylight saving time: January 1, 2017, 15:00
            var winterTimeWithDst = mstWithDstNodaTz.AtStrictly(localWinterDate);

            // Both time zones have the same time during winter
            Console.WriteLine($"Winter w/o DST: {winterTimeWithoutDst}"); // 2017-01-01T15:00:00 US Mountain Standard Time (-07)
            Console.WriteLine($"Winter w/ DST: {winterTimeWithDst}");     // 2017-01-01T15:00:00 Mountain Standard Time (-07)

            // add 180 days to get June 30, 2017
            var sixMonthsToSummer = Duration.FromTimeSpan(new TimeSpan(180, 0, 0, 0));

            // During summer, e.g. on June 30, Arizona without daylight saving time is 1 hour behind.
            Console.WriteLine($"Summer w/o DST: {winterTimeWithoutDst + sixMonthsToSummer}"); // 2017-06-30T15:00:00 US Mountain Standard Time (-07)
            Console.WriteLine($"Summer w/ DST: {winterTimeWithDst + sixMonthsToSummer}");     // 2017-06-30T16:00:00 Mountain Standard Time (-06)
        }
示例#6
0
        public void LocalZoneIsNull()
        {
            var systemZone = TimeZoneInfo.CreateCustomTimeZone("Normal zone", TimeSpan.Zero, "Display", "Standard");

            using (TimeZoneInfoReplacer.Replace(null, systemZone))
            {
                Assert.Throws <InvalidOperationException>(() => BclDateTimeZone.ForSystemDefault());
            }
        }
        public void AllZonesStartAndEndOfTime(TimeZoneInfo windowsZone)
        {
            var nodaZone      = BclDateTimeZone.FromTimeZoneInfo(windowsZone);
            var firstInterval = nodaZone.GetZoneInterval(Instant.MinValue);

            Assert.IsFalse(firstInterval.HasStart);
            var lastInterval = nodaZone.GetZoneInterval(Instant.MaxValue);

            Assert.IsFalse(lastInterval.HasEnd);
        }
示例#8
0
        public void AreWindowsStyleRules(TimeZoneInfo zone, string id)
        {
            var expected = !TestHelper.IsRunningOnDotNetCoreUnix;
            var rules    = zone.GetAdjustmentRules();

            if (rules is null || rules.Length == 0)
            {
                return;
            }
            Assert.AreEqual(expected, BclDateTimeZone.AreWindowsStyleRules(rules));
        }
        public void ForSystemDefault()
        {
            // Assume that the local time zone doesn't change between two calls...
            TimeZoneInfo    local      = TimeZoneInfo.Local;
            BclDateTimeZone nodaLocal1 = BclDateTimeZone.ForSystemDefault();
            BclDateTimeZone nodaLocal2 = BclDateTimeZone.ForSystemDefault();

            // Check it's actually the right zone
            Assert.AreSame(local, nodaLocal1.OriginalZone);
            // Check it's cached
            Assert.AreSame(nodaLocal1, nodaLocal2);
        }
示例#10
0
        private void ValidateZoneEveryWeek(TimeZoneInfo windowsZone)
        {
            var nodaZone = BclDateTimeZone.FromTimeZoneInfo(windowsZone);

            Instant instant = Instant.FromUtc(1950, 1, 1, 0, 0);
            Instant end     = Instant.FromUtc(2050, 1, 1, 0, 0);

            while (instant < end)
            {
                ValidateZoneEquality(instant, nodaZone, windowsZone);
                instant += Duration.OneWeek;
            }
        }
示例#11
0
        public void AwkwardLeapYears()
        {
            // This mimics the data on Mono on Linux for Europe/Malta, where there's a BCL adjustment rule for
            // each rule for quite a long time. One of those years is 1948, and the daylight transition is Feburary
            // 29th. That then fails when we try to build a ZoneInterval at the end of that year.
            // See https://github.com/nodatime/nodatime/issues/743 for more details. We've simplified this to just
            // a single rule here...

            // Amusingly, trying to reproduce the test on Mono with a custom time zone causes Mono to throw -
            // quite possibly due to the same root cause that we're testing we've fixed in Noda Time.
            // See https://bugzilla.xamarin.com/attachment.cgi?id=21192&action=edit
            Ignore.When(TestHelper.IsRunningOnMono, "Mono throws an exception with awkward leap years");

            // .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");

            var rules = new[]
            {
                TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(
                    dateStart: new DateTime(1948, 1, 1),
                    dateEnd: new DateTime(1949, 1, 1).AddDays(-1),
                    daylightDelta: TimeSpan.FromHours(1),
                    daylightTransitionStart: TimeZoneInfo.TransitionTime.CreateFixedDateRule(timeOfDay: new DateTime(1, 1, 1, 2, 0, 0), month: 2, day: 29),
                    daylightTransitionEnd: TimeZoneInfo.TransitionTime.CreateFixedDateRule(timeOfDay: new DateTime(1, 1, 1, 3, 0, 0), month: 10, day: 3))
            };

            var bclZone  = TimeZoneInfo.CreateCustomTimeZone("Europe/Malta", TimeSpan.Zero, "Malta", "Standard", "Daylight", rules);
            var nodaZone = BclDateTimeZone.FromTimeZoneInfo(bclZone);

            var expectedTransition1 = Instant.FromUtc(1948, 2, 29, 2, 0, 0);
            var expectedTransition2 = Instant.FromUtc(1948, 10, 3, 2, 0, 0); // 3am local time

            var zoneIntervalBefore = nodaZone.GetZoneInterval(Instant.FromUtc(1947, 1, 1, 0, 0));

            Assert.AreEqual(
                new ZoneInterval("Standard", Instant.BeforeMinValue, expectedTransition1, Offset.Zero, Offset.Zero),
                zoneIntervalBefore);

            var daylightZoneInterval = nodaZone.GetZoneInterval(Instant.FromUtc(1948, 6, 1, 0, 0));

            Assert.AreEqual(
                new ZoneInterval("Daylight", expectedTransition1, expectedTransition2, Offset.FromHours(1), Offset.FromHours(1)),
                daylightZoneInterval);

            var zoneIntervalAfter = nodaZone.GetZoneInterval(Instant.FromUtc(1949, 1, 1, 0, 0));

            Assert.AreEqual(
                new ZoneInterval("Standard", expectedTransition2, Instant.AfterMaxValue, Offset.Zero, Offset.Zero),
                zoneIntervalAfter);
        }
示例#12
0
        public void AllZonesStartAndEndOfTime(TimeZoneInfo windowsZone)
        {
            if (windowsZone == null)
            {
                Assert.Ignore("Test skipped on Mono");
            }
            var nodaZone      = BclDateTimeZone.FromTimeZoneInfo(windowsZone);
            var firstInterval = nodaZone.GetZoneInterval(Instant.MinValue);

            Assert.IsFalse(firstInterval.HasStart);
            var lastInterval = nodaZone.GetZoneInterval(Instant.MaxValue);

            Assert.IsFalse(lastInterval.HasEnd);
        }
        public void AllZoneTransitions(TimeZoneInfo windowsZone)
        {
            var nodaZone = BclDateTimeZone.FromTimeZoneInfo(windowsZone);

            Instant instant = Instant.FromUtc(1800, 1, 1, 0, 0);
            Instant end     = Instant.FromUtc(2050, 1, 1, 0, 0);

            while (instant < end)
            {
                ValidateZoneEquality(instant - Duration.Epsilon, nodaZone, windowsZone);
                ValidateZoneEquality(instant, nodaZone, windowsZone);
                instant = nodaZone.GetZoneInterval(instant).RawEnd;
            }
        }
        public void Equality()
        {
            if (BclZonesOrEmptyOnMono.Count < 2)
            {
                return;
            }
            var firstEqual  = BclDateTimeZone.FromTimeZoneInfo(BclZonesOrEmptyOnMono[0]);
            var secondEqual = BclDateTimeZone.FromTimeZoneInfo(BclZonesOrEmptyOnMono[0]);
            var unequal     = BclDateTimeZone.FromTimeZoneInfo(BclZonesOrEmptyOnMono[1]);

            Assert.AreEqual(firstEqual, secondEqual);
            Assert.AreEqual(firstEqual.GetHashCode(), secondEqual.GetHashCode());
            Assert.AreNotSame(firstEqual, secondEqual);
            Assert.AreNotEqual(firstEqual, unequal);
        }
示例#15
0
        public void AllZoneTransitions(TimeZoneInfo windowsZone)
        {
            if (windowsZone == null)
            {
                Assert.Ignore("Test skipped on Mono");
            }
            var nodaZone = BclDateTimeZone.FromTimeZoneInfo(windowsZone);

            Instant instant = Instant.FromUtc(1800, 1, 1, 0, 0);
            Instant end     = Instant.FromUtc(2050, 1, 1, 0, 0);

            while (instant < end)
            {
                ValidateZoneEquality(instant - Duration.Epsilon, nodaZone, windowsZone);
                ValidateZoneEquality(instant, nodaZone, windowsZone);
                instant = nodaZone.GetZoneInterval(instant).RawEnd;
            }
        }
示例#16
0
        private void ValidateZoneEveryWeek(TimeZoneInfo windowsZone)
        {
            var nodaZone = BclDateTimeZone.FromTimeZoneInfo(windowsZone);

            // Currently .NET Core doesn't expose the information we need to determine any DST recurrence
            // after the final tzif rule. For the moment, limit how far we check.
            // See https://github.com/dotnet/corefx/issues/17117
            int endYear = TestHelper.IsRunningOnDotNetCoreUnix ? 2037 : 2050;

            Instant instant = Instant.FromUtc(1950, 1, 1, 0, 0);
            Instant end     = Instant.FromUtc(endYear, 1, 1, 0, 0);

            while (instant < end)
            {
                ValidateZoneEquality(instant, nodaZone, windowsZone);
                instant += Duration.OneWeek;
            }
        }
示例#17
0
        public void TransitionAtMidnight()
        {
            var bclZone      = GetBclZoneOrIgnore("E. South America Standard Time");
            var nodaTzdbZone = DateTimeZoneProviders.Tzdb["America/Sao_Paulo"];
            var nodaBclZone  = BclDateTimeZone.FromTimeZoneInfo(bclZone);

            // Brazil in 2012:
            // Fall back from -02:00 to -03:00 at midnight on February 26th
            var expectedFallBack = Instant.FromUtc(2012, 2, 26, 2, 0, 0);
            // Spring forward from -03:00 to -02:00 at midnight on October 21st
            var expectedSpringForward = Instant.FromUtc(2012, 10, 21, 3, 0, 0);
            // This is an arbitrary instant between the fall back and spring forward.
            var betweenTransitions = Instant.FromUtc(2012, 6, 1, 0, 0, 0);

            // Check that these transitions are as expected when we use TZDB.
            var nodaTzdbInterval = nodaTzdbZone.GetZoneInterval(betweenTransitions);

            Assert.AreEqual(expectedFallBack, nodaTzdbInterval.Start);
            Assert.AreEqual(expectedSpringForward, nodaTzdbInterval.End);

            // Check that the real BCL time zone behaves as reported in the issue: the transitions occur one millisecond early
            var expectedFallBackBclTransition = expectedFallBack - Duration.FromMilliseconds(1);

            Assert.AreEqual(TimeSpan.FromHours(-2), bclZone.GetUtcOffset(expectedFallBackBclTransition.ToDateTimeUtc() - TimeSpan.FromTicks(1)));
            Assert.AreEqual(TimeSpan.FromHours(-3), bclZone.GetUtcOffset(expectedFallBackBclTransition.ToDateTimeUtc()));

            var expectedSpringForwardBclTransition = expectedSpringForward - Duration.FromMilliseconds(1);

            Assert.AreEqual(TimeSpan.FromHours(-3), bclZone.GetUtcOffset(expectedSpringForwardBclTransition.ToDateTimeUtc() - TimeSpan.FromTicks(1)));
            Assert.AreEqual(TimeSpan.FromHours(-2), bclZone.GetUtcOffset(expectedSpringForwardBclTransition.ToDateTimeUtc()));

            // Assert that Noda Time accounts for the Windows time zone data weirdness, and corrects it to
            // a transition at midnight.
            var nodaBclInterval = nodaBclZone.GetZoneInterval(betweenTransitions);

            Assert.AreEqual(nodaTzdbInterval.Start, nodaBclInterval.Start);
            Assert.AreEqual(nodaTzdbInterval.End, nodaBclInterval.End);

            // Finally check the use case that was actually reported
            var actualStartOfDayAfterSpringForward   = nodaBclZone.AtStartOfDay(new LocalDate(2012, 10, 21));
            var expectedStartOfDayAfterSpringForward = new LocalDateTime(2012, 10, 21, 1, 0, 0).InZoneStrictly(nodaBclZone);

            Assert.AreEqual(expectedStartOfDayAfterSpringForward, actualStartOfDayAfterSpringForward);
        }
示例#18
0
        public void AllZoneTransitions(TimeZoneInfo windowsZone, string id)
        {
            var nodaZone = BclDateTimeZone.FromTimeZoneInfo(windowsZone);

            // Currently .NET Core doesn't expose the information we need to determine any DST recurrence
            // after the final tzif rule. For the moment, limit how far we check.
            // See https://github.com/dotnet/corefx/issues/17117
            int endYear = TestHelper.IsRunningOnDotNetCoreUnix ? 2037 : 2050;

            Instant instant = Instant.FromUtc(1800, 1, 1, 0, 0);
            Instant end     = Instant.FromUtc(endYear, 1, 1, 0, 0);

            while (instant < end)
            {
                ValidateZoneEquality(instant - Duration.Epsilon, nodaZone, windowsZone);
                ValidateZoneEquality(instant, nodaZone, windowsZone);
                instant = nodaZone.GetZoneInterval(instant).RawEnd;
            }
        }
示例#19
0
            private static void AssertRules(LinuxAdjustmentMultiRuleData data, IReadOnlyList <EnhancedAdjustmentRule> sourceRules)
            {
                var expectedIntervals  = data.ExpectedIntervals;
                var bclAdjustmentRules = sourceRules
                                         .Select(rule => BclAdjustmentRule.ConvertUnixRuleToBclAdjustmentRule(rule.Rule, "Standard", "Daylight", rule.ZoneStandardOffset, rule.RuleStandardOffset, rule.ForceDaylight))
                                         .ToArray();

                BclDateTimeZone.FixUnixTransitions(bclAdjustmentRules);

                // Convert our rules to a full map, as there's coalescing code in there that we want to take advantage of.
                var map = BclDateTimeZone.BuildMap(bclAdjustmentRules, Offset.FromTimeSpan(data.ZoneStandardOffset), "Standard");;

                // Get all of the zone intervals in the expected interval
                var actualIntervals = new List <ZoneInterval>();

                actualIntervals.Add(map.GetZoneInterval(expectedIntervals[0].RawStart));
                while (actualIntervals.Last().RawEnd < expectedIntervals.Last().RawEnd)
                {
                    actualIntervals.Add(map.GetZoneInterval(actualIntervals.Last().RawEnd));
                }
                Assert.AreEqual(expectedIntervals, actualIntervals);
            }
示例#20
0
        public void DateTimeMinValueStartRuleExtendsToBeginningOfTime()
        {
            var rules = new[]
            {
                // Rule for the whole of time, with DST of 1 hour commencing on March 1st
                // and ending on September 1st.
                TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(
                    DateTime.MinValue, DateTime.MaxValue.Date, TimeSpan.FromHours(1),
                    TimeZoneInfo.TransitionTime.CreateFixedDateRule(DateTime.MinValue, 3, 1),
                    TimeZoneInfo.TransitionTime.CreateFixedDateRule(DateTime.MinValue, 9, 1))
            };
            var bclZone = TimeZoneInfo.CreateCustomTimeZone("custom", baseUtcOffset: TimeSpan.Zero,
                                                            displayName: "DisplayName", standardDisplayName: "Standard",
                                                            daylightDisplayName: "Daylight",
                                                            adjustmentRules: rules);
            var nodaZone = BclDateTimeZone.FromTimeZoneInfo(bclZone);

            // Standard time in February BC 101
            Assert.AreEqual(Offset.Zero, nodaZone.GetUtcOffset(Instant.FromUtc(-100, 2, 1, 0, 0)));
            // Daylight time in July BC 101
            Assert.AreEqual(Offset.FromHours(1), nodaZone.GetUtcOffset(Instant.FromUtc(-100, 7, 1, 0, 0)));
            // Standard time in October BC 101
            Assert.AreEqual(Offset.Zero, nodaZone.GetUtcOffset(Instant.FromUtc(-100, 10, 1, 0, 0)));
        }
示例#21
0
        public static VTimeZone FromSystemTimeZone(TimeZoneInfo tzinfo, DateTime earlistDateTimeToSupport, bool includeHistoricalData)
        {
            var zone = BclDateTimeZone.FromTimeZoneInfo(tzinfo);

            return(FromDateTimeZone(zone, earlistDateTimeToSupport, includeHistoricalData));
        }
示例#22
0
        public void DisplayName(TimeZoneInfo windowsZone)
        {
            var nodaZone = BclDateTimeZone.FromTimeZoneInfo(windowsZone);

            Assert.AreEqual(windowsZone.DisplayName, nodaZone.DisplayName);
        }