Created
April 1, 2020 14:46
-
-
Save skolima/655c9b7803ad274c44f40d5221066101 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using NodaTime; | |
using NodaTime.Extensions; | |
using Xunit; | |
namespace DaylightSavingTimeTests | |
{ | |
public class DstCalculationsTests | |
{ | |
[Theory] | |
[MemberData(nameof(DstTestCases))] | |
public void ShouldCalculateTimeDifferenceAsExpected( | |
ZonedDateTime from, | |
ZonedDateTime until, | |
Duration expectedDifference, | |
string description) | |
{ | |
Assert.Equal(expectedDifference, until - from, new DurationWithMillisecondPrecisionComparer(5)); | |
} | |
public static TheoryData<ZonedDateTime, ZonedDateTime, Duration, string> DstTestCases() | |
{ | |
var clock = SystemClock.Instance; | |
var zonedClock = clock.InTzdbSystemDefaultZone(); | |
var utcDayBeforeGermanDst = Instant.FromDateTimeUtc(new DateTime(2020, 3, 28, 11, 30, 00, DateTimeKind.Utc)); | |
var utcDayAfterGermanDst = Instant.FromDateTimeUtc(new DateTime(2020, 3, 29, 15, 17, 00, DateTimeKind.Utc)); | |
var utcDayBeforePolishWinterTime = Instant.FromDateTimeUtc(new DateTime(2019, 10, 26, 13, 45, 55, DateTimeKind.Utc)); | |
var timeZoneSource = NodaTime.TimeZones.TzdbDateTimeZoneSource.Default; | |
return new TheoryData<ZonedDateTime, ZonedDateTime, Duration, string> | |
{ | |
{zonedClock.GetCurrentZonedDateTime(), clock.GetCurrentInstant().InUtc(), Duration.FromHours(0), "UtcNow and Now"}, | |
{zonedClock.GetCurrentZonedDateTime(), zonedClock.GetCurrentZonedDateTime().PlusHours(1), Duration.FromHours(1), "One hour ahead, local time"}, | |
{zonedClock.GetCurrentZonedDateTime(), zonedClock.GetCurrentZonedDateTime().PlusHours(24), Duration.FromHours(24), "One day ahead, local time"}, | |
{ | |
new ZonedDateTime(utcDayBeforeGermanDst, timeZoneSource.ForId("Europe/Berlin")), | |
new ZonedDateTime(utcDayBeforeGermanDst.Plus(Duration.FromDays(1)), timeZoneSource.ForId("Europe/Berlin")), | |
Duration.FromHours(24), | |
"One day ahead, across DST start in Germany" | |
}, | |
{ | |
new ZonedDateTime(utcDayAfterGermanDst, timeZoneSource.ForId("Europe/Berlin")), | |
new ZonedDateTime(utcDayAfterGermanDst.Minus(Duration.FromDays(2)), timeZoneSource.ForId("Europe/Berlin")), | |
Duration.FromHours(-48), | |
"Two days back, across DST start in Germany" | |
}, | |
{ | |
new ZonedDateTime(utcDayBeforePolishWinterTime, timeZoneSource.ForId("Europe/Warsaw")), | |
new ZonedDateTime(utcDayBeforePolishWinterTime.Plus(Duration.FromDays(2)), timeZoneSource.ForId("Europe/Warsaw")), | |
Duration.FromHours(48), | |
"Two days ahead, across DST end in Poland" | |
}, | |
}; | |
} | |
} | |
public class DurationWithMillisecondPrecisionComparer : IEqualityComparer<Duration> | |
{ | |
private readonly int _millisecondPrecision; | |
public DurationWithMillisecondPrecisionComparer(int millisecondPrecision) | |
{ | |
this._millisecondPrecision = millisecondPrecision; | |
} | |
public bool Equals(Duration x, Duration y) | |
{ | |
var diff = (x - y).TotalMilliseconds; | |
return Math.Abs(diff) < this._millisecondPrecision; | |
} | |
public int GetHashCode(Duration obj) | |
{ | |
return obj.GetHashCode(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment