using System; using AMWD.Common.Tests.Utils; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace AMWD.Common.Tests.Extensions { [TestClass] [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class DateTimeExtensionsTests { [TestMethod] public void ShouldReturnUtc() { // arrange var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin"); using var mock = TimeZoneInfoLocalMock.Create(timeZoneInfo); var utc = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Utc); var local = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Local); var unspecified = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Unspecified); // act var utcCorrected = utc.AsUtc(); var localCorrected = local.AsUtc(); var unspecifiedCorrected = unspecified.AsUtc(); // assert Assert.AreEqual(DateTimeKind.Utc, utcCorrected.Kind); Assert.AreEqual(DateTimeKind.Utc, localCorrected.Kind); Assert.AreEqual(DateTimeKind.Utc, unspecifiedCorrected.Kind); Assert.AreEqual(utc, utcCorrected); Assert.AreEqual(utc.AddHours(-1), localCorrected); Assert.AreEqual(utc, unspecifiedCorrected); } [TestMethod] public void ShouldReturnLocal() { // arrange var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin"); using var mock = TimeZoneInfoLocalMock.Create(timeZoneInfo); var utc = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Utc); var local = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Local); var unspecified = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Unspecified); // act var utcCorrected = utc.AsLocal(); var localCorrected = local.AsLocal(); var unspecifiedCorrected = unspecified.AsLocal(); // assert Assert.AreEqual(DateTimeKind.Local, utcCorrected.Kind); Assert.AreEqual(DateTimeKind.Local, localCorrected.Kind); Assert.AreEqual(DateTimeKind.Local, unspecifiedCorrected.Kind); Assert.AreEqual(local.AddHours(1), utcCorrected); Assert.AreEqual(local, localCorrected); Assert.AreEqual(local, unspecifiedCorrected); } [TestMethod] public void ShouldReturnCorrectUtcAlignmentDaylightSavingEnd() { // arrange var utcNow = new DateTime(2021, 10, 30, 12, 15, 30, 45, DateTimeKind.Utc); var intervalThreeSeconds = TimeSpan.FromSeconds(3); var intervalSixMinutes = TimeSpan.FromMinutes(6); var intervalTwoHours = TimeSpan.FromHours(2); var intervalDay = TimeSpan.FromDays(1); var offsetTwoMinutes = TimeSpan.FromMinutes(2); var offsetFourHours = TimeSpan.FromHours(4); // act var diffThreeSeconds = intervalThreeSeconds.GetAlignedInterval(utcNow); var diffSixMinutes = intervalSixMinutes.GetAlignedInterval(utcNow); var diffTwoHours = intervalTwoHours.GetAlignedInterval(utcNow); var diffDay = intervalDay.GetAlignedInterval(utcNow); var diffTwoHoursOffset = intervalTwoHours.GetAlignedInterval(utcNow, offsetTwoMinutes); var diffDayOffset = intervalDay.GetAlignedInterval(utcNow, offsetFourHours); // assert Assert.AreEqual(TimeSpan.Parse("00:00:02.955"), diffThreeSeconds); Assert.AreEqual(TimeSpan.Parse("00:02:29.955"), diffSixMinutes); Assert.AreEqual(TimeSpan.Parse("01:44:29.955"), diffTwoHours); Assert.AreEqual(TimeSpan.Parse("11:44:29.955"), diffDay); Assert.AreEqual(TimeSpan.Parse("01:46:29.955"), diffTwoHoursOffset); Assert.AreEqual(TimeSpan.Parse("15:44:29.955"), diffDayOffset); // must be the same whether daylight saving has ended } [TestMethod] public void ShouldReturnCorrectUtcAlignmentDaylightSavingStart() { // arrange var utcNow = new DateTime(2022, 3, 26, 12, 15, 30, 45, DateTimeKind.Utc); var intervalThreeSeconds = TimeSpan.FromSeconds(3); var intervalSixMinutes = TimeSpan.FromMinutes(6); var intervalTwoHours = TimeSpan.FromHours(2); var intervalDay = TimeSpan.FromDays(1); var offsetTwoMinutes = TimeSpan.FromMinutes(2); var offsetFourHours = TimeSpan.FromHours(4); // act var diffThreeSeconds = intervalThreeSeconds.GetAlignedInterval(utcNow); var diffSixMinutes = intervalSixMinutes.GetAlignedInterval(utcNow); var diffTwoHours = intervalTwoHours.GetAlignedInterval(utcNow); var diffDay = intervalDay.GetAlignedInterval(utcNow); var diffTwoHoursOffset = intervalTwoHours.GetAlignedInterval(utcNow, offsetTwoMinutes); var diffDayOffset = intervalDay.GetAlignedInterval(utcNow, offsetFourHours); // assert Assert.AreEqual(TimeSpan.Parse("00:00:02.955"), diffThreeSeconds); Assert.AreEqual(TimeSpan.Parse("00:02:29.955"), diffSixMinutes); Assert.AreEqual(TimeSpan.Parse("01:44:29.955"), diffTwoHours); Assert.AreEqual(TimeSpan.Parse("11:44:29.955"), diffDay); Assert.AreEqual(TimeSpan.Parse("01:46:29.955"), diffTwoHoursOffset); Assert.AreEqual(TimeSpan.Parse("15:44:29.955"), diffDayOffset); // must be the same whether daylight saving has started } [TestMethod] public void ShouldReturnCorrectLocalAlignmentDaylightSavingEnd() { // arrange var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin"); using var mock = TimeZoneInfoLocalMock.Create(timeZoneInfo); var utcNow = new DateTime(2021, 10, 30, 12, 15, 30, 45, DateTimeKind.Local); var intervalThreeSeconds = TimeSpan.FromSeconds(3); var intervalSixMinutes = TimeSpan.FromMinutes(6); var intervalTwoHours = TimeSpan.FromHours(2); var intervalDay = TimeSpan.FromDays(1); var offsetTwoMinutes = TimeSpan.FromMinutes(2); var offsetFourHours = TimeSpan.FromHours(4); // act var diffThreeSeconds = intervalThreeSeconds.GetAlignedInterval(utcNow); var diffSixMinutes = intervalSixMinutes.GetAlignedInterval(utcNow); var diffTwoHours = intervalTwoHours.GetAlignedInterval(utcNow); var diffDay = intervalDay.GetAlignedInterval(utcNow); var diffTwoHoursOffset = intervalTwoHours.GetAlignedInterval(utcNow, offsetTwoMinutes); var diffDayOffset = intervalDay.GetAlignedInterval(utcNow, offsetFourHours); // assert Assert.AreEqual(TimeSpan.Parse("00:00:02.955"), diffThreeSeconds); Assert.AreEqual(TimeSpan.Parse("00:02:29.955"), diffSixMinutes); Assert.AreEqual(TimeSpan.Parse("01:44:29.955"), diffTwoHours); Assert.AreEqual(TimeSpan.Parse("11:44:29.955"), diffDay); Assert.AreEqual(TimeSpan.Parse("01:46:29.955"), diffTwoHoursOffset); Assert.AreEqual(TimeSpan.Parse("14:44:29.955"), diffDayOffset); // has to be minus one hour due to daylight saving ended } [TestMethod] public void ShouldReturnCorrectLocalAlignmentDaylightSavingStart() { // arrange var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin"); using var mock = TimeZoneInfoLocalMock.Create(timeZoneInfo); var utcNow = new DateTime(2022, 3, 26, 12, 15, 30, 45, DateTimeKind.Local); var intervalThreeSeconds = TimeSpan.FromSeconds(3); var intervalSixMinutes = TimeSpan.FromMinutes(6); var intervalTwoHours = TimeSpan.FromHours(2); var intervalDay = TimeSpan.FromDays(1); var offsetTwoMinutes = TimeSpan.FromMinutes(2); var offsetFourHours = TimeSpan.FromHours(4); // act var diffThreeSeconds = intervalThreeSeconds.GetAlignedInterval(utcNow); var diffSixMinutes = intervalSixMinutes.GetAlignedInterval(utcNow); var diffTwoHours = intervalTwoHours.GetAlignedInterval(utcNow); var diffDay = intervalDay.GetAlignedInterval(utcNow); var diffTwoHoursOffset = intervalTwoHours.GetAlignedInterval(utcNow, offsetTwoMinutes); var diffDayOffset = intervalDay.GetAlignedInterval(utcNow, offsetFourHours); // assert Assert.AreEqual(TimeSpan.Parse("00:00:02.955"), diffThreeSeconds); Assert.AreEqual(TimeSpan.Parse("00:02:29.955"), diffSixMinutes); Assert.AreEqual(TimeSpan.Parse("01:44:29.955"), diffTwoHours); Assert.AreEqual(TimeSpan.Parse("11:44:29.955"), diffDay); Assert.AreEqual(TimeSpan.Parse("01:46:29.955"), diffTwoHoursOffset); Assert.AreEqual(TimeSpan.Parse("16:44:29.955"), diffDayOffset); // has to be plus one hour due to daylight saving started } [TestMethod] public void ShouldReturnCorrectShortStringForTimeSpan() { // arrange var timeSpan = TimeSpan.Parse("1.10:11:12.345"); var negativeTimeSpan = TimeSpan.FromDays(-1.234); // act string shortString = timeSpan.ToShortString(withMilliseconds: false); string shortStringWithMillis = timeSpan.ToShortString(withMilliseconds: true); string shortStringNegative = negativeTimeSpan.ToShortString(withMilliseconds: true); // assert Assert.AreEqual("1d 10h 11m 12s", shortString); Assert.AreEqual("1d 10h 11m 12s 345ms", shortStringWithMillis); Assert.AreEqual("-1d 5h 36m 57s 600ms", shortStringNegative); } [TestMethod] public void ShouldRoundToSecond() { // arrange var timestampUp = new DateTime(2021, 11, 16, 20, 15, 30, 500); var timestampDown = new DateTime(2021, 11, 16, 20, 15, 30, 499); var timespanUp = new TimeSpan(1, 2, 3, 4, 500); var timespanDown = new TimeSpan(1, 2, 3, 4, 499); // act var timestampUpRounded = timestampUp.RoundToSecond(); var timestampDownRounded = timestampDown.RoundToSecond(); var timespanUpRounded = timespanUp.RoundToSecond(); var timespanDownRounded = timespanDown.RoundToSecond(); // assert Assert.AreNotEqual(timestampUp, timestampUpRounded); Assert.AreEqual(DateTime.Parse("2021-11-16 20:15:31.000"), timestampUpRounded); Assert.AreNotEqual(timestampDown, timestampDownRounded); Assert.AreEqual(DateTime.Parse("2021-11-16 20:15:30.000"), timestampDownRounded); Assert.AreNotEqual(timespanUp, timespanUpRounded); Assert.AreEqual(TimeSpan.Parse("1.02:03:05.000"), timespanUpRounded); Assert.AreNotEqual(timespanDown, timespanDownRounded); Assert.AreEqual(TimeSpan.Parse("1.02:03:04.000"), timespanDownRounded); } [TestMethod] public void ShouldRoundToMinute() { // arrange var timestampUp = new DateTime(2021, 11, 16, 20, 15, 30, 0); var timestampDown = new DateTime(2021, 11, 16, 20, 15, 29, 999); var timespanUp = new TimeSpan(1, 2, 3, 30, 0); var timespanDown = new TimeSpan(1, 2, 3, 29, 999); // act var timestampUpRounded = timestampUp.RoundToMinute(); var timestampDownRounded = timestampDown.RoundToMinute(); var timespanUpRounded = timespanUp.RoundToMinute(); var timespanDownRounded = timespanDown.RoundToMinute(); // assert Assert.AreNotEqual(timestampUp, timestampUpRounded); Assert.AreEqual(DateTime.Parse("2021-11-16 20:16:00.000"), timestampUpRounded); Assert.AreNotEqual(timestampDown, timestampDownRounded); Assert.AreEqual(DateTime.Parse("2021-11-16 20:15:00.000"), timestampDownRounded); Assert.AreNotEqual(timespanUp, timespanUpRounded); Assert.AreEqual(TimeSpan.Parse("1.02:04:00.000"), timespanUpRounded); Assert.AreNotEqual(timespanDown, timespanDownRounded); Assert.AreEqual(TimeSpan.Parse("1.02:03:00.000"), timespanDownRounded); } [TestMethod] public void ShouldRoundToHour() { // arrange var timestampUp = new DateTime(2021, 11, 16, 20, 30, 0, 0); var timestampDown = new DateTime(2021, 11, 16, 20, 29, 59, 999); var timespanUp = new TimeSpan(1, 2, 30, 0, 0); var timespanDown = new TimeSpan(1, 2, 29, 59, 999); // act var timestampUpRounded = timestampUp.RoundToHour(); var timestampDownRounded = timestampDown.RoundToHour(); var timespanUpRounded = timespanUp.RoundToHour(); var timespanDownRounded = timespanDown.RoundToHour(); // assert Assert.AreNotEqual(timestampUp, timestampUpRounded); Assert.AreEqual(DateTime.Parse("2021-11-16 21:00:00.000"), timestampUpRounded); Assert.AreNotEqual(timestampDown, timestampDownRounded); Assert.AreEqual(DateTime.Parse("2021-11-16 20:00:00.000"), timestampDownRounded); Assert.AreNotEqual(timespanUp, timespanUpRounded); Assert.AreEqual(TimeSpan.Parse("1.03:00:00.000"), timespanUpRounded); Assert.AreNotEqual(timespanDown, timespanDownRounded); Assert.AreEqual(TimeSpan.Parse("1.02:00:00.000"), timespanDownRounded); } [TestMethod] public void ShouldRoundToDay() { // arrange var timestampUp = new DateTime(2021, 11, 16, 12, 0, 0, 0); var timestampDown = new DateTime(2021, 11, 16, 11, 59, 59, 999); var timespanUp = new TimeSpan(1, 12, 0, 0, 0); var timespanDown = new TimeSpan(1, 11, 59, 59, 999); // act var timestampUpRounded = timestampUp.RoundToDay(); var timestampDownRounded = timestampDown.RoundToDay(); var timespanUpRounded = timespanUp.RoundToDay(); var timespanDownRounded = timespanDown.RoundToDay(); // assert Assert.AreNotEqual(timestampUp, timestampUpRounded); Assert.AreEqual(DateTime.Parse("2021-11-17 00:00:00.000"), timestampUpRounded); Assert.AreNotEqual(timestampDown, timestampDownRounded); Assert.AreEqual(DateTime.Parse("2021-11-16 00:00:00.000"), timestampDownRounded); Assert.AreNotEqual(timespanUp, timespanUpRounded); Assert.AreEqual(TimeSpan.Parse("2.00:00:00.000"), timespanUpRounded); Assert.AreNotEqual(timespanDown, timespanDownRounded); Assert.AreEqual(TimeSpan.Parse("1.00:00:00.000"), timespanDownRounded); } } }