GetAlignedInterval nun in UTC und Local unterschieden (Local beachtet Sommer-/Winterzeit); UnitTests begonnen
This commit is contained in:
18
AMWD.Common.Tests/AMWD.Common.Tests.csproj
Normal file
18
AMWD.Common.Tests/AMWD.Common.Tests.csproj
Normal file
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AMWD.Common\AMWD.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
318
AMWD.Common.Tests/Extensions/DateTimeExtensionsTests.cs
Normal file
318
AMWD.Common.Tests/Extensions/DateTimeExtensionsTests.cs
Normal file
@@ -0,0 +1,318 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace AMWD.Common.Tests.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
public class DateTimeExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReturnUtc()
|
||||
{
|
||||
// arrange
|
||||
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 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 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 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");
|
||||
|
||||
// act
|
||||
string shortString = timeSpan.ToShortString(withMilliseconds: false);
|
||||
string shortStringWithMillis = timeSpan.ToShortString(withMilliseconds: true);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("1d 10h 11m 12s", shortString);
|
||||
Assert.AreEqual("1d 10h 11m 12s 345ms", shortStringWithMillis);
|
||||
}
|
||||
|
||||
[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);
|
||||
}
|
||||
}
|
||||
}
|
||||
107
AMWD.Common.Tests/Extensions/EnumExtensionsTests.cs
Normal file
107
AMWD.Common.Tests/Extensions/EnumExtensionsTests.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AMWD.Common.Tests.Utils;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using DescriptionAttribute = System.ComponentModel.DescriptionAttribute;
|
||||
|
||||
namespace AMWD.Common.Tests.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
public class EnumExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReturnEmptyList()
|
||||
{
|
||||
// arrange
|
||||
var enumValue = TestEnum.Two;
|
||||
|
||||
// act
|
||||
var customList = enumValue.GetAttributes<CustomMultipleAttribute>();
|
||||
var descriptionList = enumValue.GetAttributes<DescriptionAttribute>();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(customList);
|
||||
Assert.IsFalse(customList.Any());
|
||||
Assert.IsNotNull(descriptionList);
|
||||
Assert.IsFalse(descriptionList.Any());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnList()
|
||||
{
|
||||
// arrange
|
||||
var enumValue = TestEnum.Zero;
|
||||
|
||||
// act
|
||||
var customList = enumValue.GetAttributes<CustomMultipleAttribute>();
|
||||
var descriptionList = enumValue.GetAttributes<DescriptionAttribute>();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(customList);
|
||||
Assert.IsTrue(customList.Any());
|
||||
Assert.AreEqual(2, customList.Count());
|
||||
Assert.IsNotNull(descriptionList);
|
||||
Assert.IsTrue(descriptionList.Any());
|
||||
Assert.AreEqual(1, descriptionList.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnNothing()
|
||||
{
|
||||
// arrange
|
||||
var enumValue = TestEnum.Two;
|
||||
|
||||
// act
|
||||
var customAttribute = enumValue.GetAttribute<CustomMultipleAttribute>();
|
||||
var descriptionAttribute = enumValue.GetAttribute<DescriptionAttribute>();
|
||||
|
||||
// assert
|
||||
Assert.IsNull(customAttribute);
|
||||
Assert.IsNull(descriptionAttribute);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnFirstAttribute()
|
||||
{
|
||||
// arrange
|
||||
var enumValue = TestEnum.Zero;
|
||||
|
||||
// act
|
||||
var customAttribute = enumValue.GetAttribute<CustomMultipleAttribute>();
|
||||
var descriptionAttribute = enumValue.GetAttribute<DescriptionAttribute>();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(customAttribute);
|
||||
Assert.AreEqual("nix", customAttribute.Name);
|
||||
Assert.IsNotNull(descriptionAttribute);
|
||||
Assert.AreEqual("Null", descriptionAttribute.Description);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnDescriptionOrStringRepresentation()
|
||||
{
|
||||
// arrange
|
||||
var enumWithDescription = TestEnum.One;
|
||||
var enumWithoutDescripton = TestEnum.Two;
|
||||
|
||||
// act
|
||||
string description = enumWithDescription.GetDescription();
|
||||
string noDescription = enumWithoutDescripton.GetDescription();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("Eins", description);
|
||||
Assert.AreEqual(enumWithoutDescripton.ToString(), noDescription);
|
||||
}
|
||||
|
||||
internal enum TestEnum
|
||||
{
|
||||
[CustomMultiple("nix")]
|
||||
[CustomMultiple("Null")]
|
||||
[Description("Null")]
|
||||
Zero,
|
||||
[Description("Eins")]
|
||||
One,
|
||||
Two,
|
||||
}
|
||||
}
|
||||
}
|
||||
15
AMWD.Common.Tests/Utils/CustomMultipleAttribute.cs
Normal file
15
AMWD.Common.Tests/Utils/CustomMultipleAttribute.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace AMWD.Common.Tests.Utils
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
|
||||
internal class CustomMultipleAttribute : Attribute
|
||||
{
|
||||
public CustomMultipleAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.Text;
|
||||
|
||||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("AMWD.Common.Tests")]
|
||||
|
||||
namespace System
|
||||
{
|
||||
/// <summary>
|
||||
@@ -41,23 +43,44 @@ namespace System
|
||||
|
||||
#endregion Kind
|
||||
|
||||
#region Aligned Interval
|
||||
|
||||
/// <summary>
|
||||
/// Aligns the <see cref="TimeSpan"/> to the clock.
|
||||
/// Aligns the <see cref="TimeSpan"/> to the UTC clock.
|
||||
/// </summary>
|
||||
/// <param name="timeSpan">The timespan to align.</param>
|
||||
/// <param name="offset">A specific offset to the timespan.</param>
|
||||
/// <returns>The timespan until the aligned time.</returns>
|
||||
public static TimeSpan GetAlignedInterval(this TimeSpan timeSpan, TimeSpan offset = default)
|
||||
public static TimeSpan GetAlignedIntervalUtc(this TimeSpan timeSpan, TimeSpan offset = default)
|
||||
=> timeSpan.GetAlignedInterval(DateTime.UtcNow, offset);
|
||||
|
||||
/// <summary>
|
||||
/// Aligns the <see cref="TimeSpan"/> to the local clock and respects daylight saving time.
|
||||
/// </summary>
|
||||
/// <param name="timeSpan">The timespan to align.</param>
|
||||
/// <param name="offset">A specific offset to the timespan.</param>
|
||||
/// <returns>The timespan until the aligned time.</returns>
|
||||
public static TimeSpan GetAlignedIntervalLocal(this TimeSpan timeSpan, TimeSpan offset = default)
|
||||
=> timeSpan.GetAlignedInterval(DateTime.Now, offset);
|
||||
|
||||
internal static TimeSpan GetAlignedInterval(this TimeSpan timeSpan, DateTime now, TimeSpan offset = default)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var nextTime = new DateTime(now.Ticks / timeSpan.Ticks * timeSpan.Ticks) + offset;
|
||||
var nowWithOffset = new DateTimeOffset(now);
|
||||
|
||||
if (nextTime <= now)
|
||||
nextTime += timeSpan;
|
||||
var nextTime = new DateTime(nowWithOffset.Ticks / timeSpan.Ticks * timeSpan.Ticks, now.Kind).Add(offset);
|
||||
var nextTimeWithOffset = new DateTimeOffset(nextTime);
|
||||
|
||||
return nextTime - now;
|
||||
if (nextTimeWithOffset <= nowWithOffset)
|
||||
nextTimeWithOffset = nextTimeWithOffset.Add(timeSpan);
|
||||
|
||||
if (now.Kind == DateTimeKind.Local)
|
||||
return nextTimeWithOffset.LocalDateTime - nowWithOffset.LocalDateTime;
|
||||
|
||||
return nextTimeWithOffset - nowWithOffset;
|
||||
}
|
||||
|
||||
#endregion Aligned Interval
|
||||
|
||||
/// <summary>
|
||||
/// Prints the timespan as shortended string.
|
||||
/// </summary>
|
||||
@@ -94,9 +117,7 @@ namespace System
|
||||
/// <returns></returns>
|
||||
|
||||
public static DateTime RoundToSecond(this DateTime dt)
|
||||
{
|
||||
return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerSecond), dt.Kind);
|
||||
}
|
||||
=> new(RoundTicks(dt.Ticks, TimeSpan.TicksPerSecond), dt.Kind);
|
||||
|
||||
/// <summary>
|
||||
/// Rounds the <see cref="DateTime"/> to full minutes.
|
||||
@@ -104,9 +125,7 @@ namespace System
|
||||
/// <param name="dt">The time value to round.</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime RoundToMinute(this DateTime dt)
|
||||
{
|
||||
return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerMinute), dt.Kind);
|
||||
}
|
||||
=> new(RoundTicks(dt.Ticks, TimeSpan.TicksPerMinute), dt.Kind);
|
||||
|
||||
/// <summary>
|
||||
/// Rounds the <see cref="DateTime"/> to full hours.
|
||||
@@ -114,9 +133,7 @@ namespace System
|
||||
/// <param name="dt">The time value to round.</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime RoundToHour(this DateTime dt)
|
||||
{
|
||||
return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerHour), dt.Kind);
|
||||
}
|
||||
=> new(RoundTicks(dt.Ticks, TimeSpan.TicksPerHour), dt.Kind);
|
||||
|
||||
/// <summary>
|
||||
/// Rounds the <see cref="DateTime"/> to full days.
|
||||
@@ -124,9 +141,7 @@ namespace System
|
||||
/// <param name="dt">The time value to round.</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime RoundToDay(this DateTime dt)
|
||||
{
|
||||
return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerDay), dt.Kind);
|
||||
}
|
||||
=> new(RoundTicks(dt.Ticks, TimeSpan.TicksPerDay), dt.Kind);
|
||||
|
||||
#endregion Round DateTime
|
||||
|
||||
@@ -138,9 +153,7 @@ namespace System
|
||||
/// <param name="timeSpan">The time value to round.</param>
|
||||
/// <returns></returns>
|
||||
public static TimeSpan RoundToSecond(this TimeSpan timeSpan)
|
||||
{
|
||||
return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerSecond));
|
||||
}
|
||||
=> new(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerSecond));
|
||||
|
||||
/// <summary>
|
||||
/// Rounds the <see cref="TimeSpan"/> to full minutes.
|
||||
@@ -148,9 +161,7 @@ namespace System
|
||||
/// <param name="timeSpan">The time value to round.</param>
|
||||
/// <returns></returns>
|
||||
public static TimeSpan RoundToMinute(this TimeSpan timeSpan)
|
||||
{
|
||||
return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerMinute));
|
||||
}
|
||||
=> new(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerMinute));
|
||||
|
||||
/// <summary>
|
||||
/// Rounds the <see cref="TimeSpan"/> to full hours.
|
||||
@@ -158,9 +169,7 @@ namespace System
|
||||
/// <param name="timeSpan">The time value to round.</param>
|
||||
/// <returns></returns>
|
||||
public static TimeSpan RoundToHour(this TimeSpan timeSpan)
|
||||
{
|
||||
return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerHour));
|
||||
}
|
||||
=> new(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerHour));
|
||||
|
||||
/// <summary>
|
||||
/// Rounds the <see cref="TimeSpan"/> to full days.
|
||||
@@ -168,15 +177,11 @@ namespace System
|
||||
/// <param name="timeSpan">The time value to round.</param>
|
||||
/// <returns></returns>
|
||||
public static TimeSpan RoundToDay(this TimeSpan timeSpan)
|
||||
{
|
||||
return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerDay));
|
||||
}
|
||||
=> new(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerDay));
|
||||
|
||||
#endregion Round TimeSpan
|
||||
|
||||
private static long RoundTicks(long ticks, long value)
|
||||
{
|
||||
return (ticks + value / 2) / value * value;
|
||||
}
|
||||
=> (ticks + value / 2) / value * value;
|
||||
}
|
||||
}
|
||||
|
||||
20
Common.sln
20
Common.sln
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31729.503
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AMWD.Common", "AMWD.Common\AMWD.Common.csproj", "{F512C474-B670-4E47-911E-7C0674AA8E7E}"
|
||||
EndProject
|
||||
@@ -20,6 +20,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AMWD.Common.Tests", "AMWD.Common.Tests\AMWD.Common.Tests.csproj", "{086E3C11-454A-4C8F-AEAA-215BAE9C443F}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F2C7556A-99EB-43EB-8954-56A24AFE928F}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E5DF156A-6C8B-4004-BA4C-A8DDE6FD3ECD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -38,10 +44,20 @@ Global
|
||||
{7091CECF-C981-4FB9-9CC6-91C4E65A6356}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7091CECF-C981-4FB9-9CC6-91C4E65A6356}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7091CECF-C981-4FB9-9CC6-91C4E65A6356}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{086E3C11-454A-4C8F-AEAA-215BAE9C443F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{086E3C11-454A-4C8F-AEAA-215BAE9C443F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{086E3C11-454A-4C8F-AEAA-215BAE9C443F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{086E3C11-454A-4C8F-AEAA-215BAE9C443F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{F512C474-B670-4E47-911E-7C0674AA8E7E} = {F2C7556A-99EB-43EB-8954-56A24AFE928F}
|
||||
{725F40C9-8172-487F-B3D0-D7E38B4DB197} = {F2C7556A-99EB-43EB-8954-56A24AFE928F}
|
||||
{7091CECF-C981-4FB9-9CC6-91C4E65A6356} = {F2C7556A-99EB-43EB-8954-56A24AFE928F}
|
||||
{086E3C11-454A-4C8F-AEAA-215BAE9C443F} = {E5DF156A-6C8B-4004-BA4C-A8DDE6FD3ECD}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {961E8DF8-DDF5-4D10-A510-CE409E9962AC}
|
||||
EndGlobalSection
|
||||
|
||||
Reference in New Issue
Block a user