diff --git a/AMWD.Common.Tests/AMWD.Common.Tests.csproj b/AMWD.Common.Tests/AMWD.Common.Tests.csproj
new file mode 100644
index 0000000..63f846d
--- /dev/null
+++ b/AMWD.Common.Tests/AMWD.Common.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net6.0
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AMWD.Common.Tests/Extensions/DateTimeExtensionsTests.cs b/AMWD.Common.Tests/Extensions/DateTimeExtensionsTests.cs
new file mode 100644
index 0000000..c32b41a
--- /dev/null
+++ b/AMWD.Common.Tests/Extensions/DateTimeExtensionsTests.cs
@@ -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);
+ }
+ }
+}
diff --git a/AMWD.Common.Tests/Extensions/EnumExtensionsTests.cs b/AMWD.Common.Tests/Extensions/EnumExtensionsTests.cs
new file mode 100644
index 0000000..62f91bc
--- /dev/null
+++ b/AMWD.Common.Tests/Extensions/EnumExtensionsTests.cs
@@ -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();
+ var descriptionList = enumValue.GetAttributes();
+
+ // 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();
+ var descriptionList = enumValue.GetAttributes();
+
+ // 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();
+ var descriptionAttribute = enumValue.GetAttribute();
+
+ // assert
+ Assert.IsNull(customAttribute);
+ Assert.IsNull(descriptionAttribute);
+ }
+
+ [TestMethod]
+ public void ShouldReturnFirstAttribute()
+ {
+ // arrange
+ var enumValue = TestEnum.Zero;
+
+ // act
+ var customAttribute = enumValue.GetAttribute();
+ var descriptionAttribute = enumValue.GetAttribute();
+
+ // 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,
+ }
+ }
+}
diff --git a/AMWD.Common.Tests/Utils/CustomMultipleAttribute.cs b/AMWD.Common.Tests/Utils/CustomMultipleAttribute.cs
new file mode 100644
index 0000000..413fae0
--- /dev/null
+++ b/AMWD.Common.Tests/Utils/CustomMultipleAttribute.cs
@@ -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; }
+ }
+}
diff --git a/AMWD.Common/Extensions/DateTimeExtensions.cs b/AMWD.Common/Extensions/DateTimeExtensions.cs
index 7f229d5..dbd554a 100644
--- a/AMWD.Common/Extensions/DateTimeExtensions.cs
+++ b/AMWD.Common/Extensions/DateTimeExtensions.cs
@@ -1,5 +1,7 @@
using System.Text;
+[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("AMWD.Common.Tests")]
+
namespace System
{
///
@@ -41,23 +43,44 @@ namespace System
#endregion Kind
+ #region Aligned Interval
+
///
- /// Aligns the to the clock.
+ /// Aligns the to the UTC clock.
///
/// The timespan to align.
/// A specific offset to the timespan.
/// The timespan until the aligned time.
- 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);
+
+ ///
+ /// Aligns the to the local clock and respects daylight saving time.
+ ///
+ /// The timespan to align.
+ /// A specific offset to the timespan.
+ /// The timespan until the aligned time.
+ 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
+
///
/// Prints the timespan as shortended string.
///
@@ -94,9 +117,7 @@ namespace System
///
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);
///
/// Rounds the to full minutes.
@@ -104,9 +125,7 @@ namespace System
/// The time value to round.
///
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);
///
/// Rounds the to full hours.
@@ -114,9 +133,7 @@ namespace System
/// The time value to round.
///
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);
///
/// Rounds the to full days.
@@ -124,9 +141,7 @@ namespace System
/// The time value to round.
///
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
/// The time value to round.
///
public static TimeSpan RoundToSecond(this TimeSpan timeSpan)
- {
- return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerSecond));
- }
+ => new(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerSecond));
///
/// Rounds the to full minutes.
@@ -148,9 +161,7 @@ namespace System
/// The time value to round.
///
public static TimeSpan RoundToMinute(this TimeSpan timeSpan)
- {
- return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerMinute));
- }
+ => new(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerMinute));
///
/// Rounds the to full hours.
@@ -158,9 +169,7 @@ namespace System
/// The time value to round.
///
public static TimeSpan RoundToHour(this TimeSpan timeSpan)
- {
- return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerHour));
- }
+ => new(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerHour));
///
/// Rounds the to full days.
@@ -168,15 +177,11 @@ namespace System
/// The time value to round.
///
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;
}
}
diff --git a/Common.sln b/Common.sln
index 24ea6f4..3a5745a 100644
--- a/Common.sln
+++ b/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