public void DisplayName(NamedWrapper <TimeZoneInfo> windowsZoneWrapper) { var windowsZone = windowsZoneWrapper.Value; var nodaZone = BclDateTimeZone.FromTimeZoneInfo(windowsZone); Assert.AreEqual(windowsZone.DisplayName, nodaZone.DisplayName); }
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); }
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()); }
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) }
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); }
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); }
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; } }
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); }
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); }
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; } }
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; } }
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); }
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; } }
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); }
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))); }
public static VTimeZone FromSystemTimeZone(TimeZoneInfo tzinfo, DateTime earlistDateTimeToSupport, bool includeHistoricalData) { var zone = BclDateTimeZone.FromTimeZoneInfo(tzinfo); return(FromDateTimeZone(zone, earlistDateTimeToSupport, includeHistoricalData)); }
public void DisplayName(TimeZoneInfo windowsZone) { var nodaZone = BclDateTimeZone.FromTimeZoneInfo(windowsZone); Assert.AreEqual(windowsZone.DisplayName, nodaZone.DisplayName); }