diff --git a/src/Umbraco.Core/Extensions/DateTimeExtensions.cs b/src/Umbraco.Core/Extensions/DateTimeExtensions.cs
index 00191e5a76..9fadb6217a 100644
--- a/src/Umbraco.Core/Extensions/DateTimeExtensions.cs
+++ b/src/Umbraco.Core/Extensions/DateTimeExtensions.cs
@@ -5,6 +5,9 @@ using System.Globalization;
namespace Umbraco.Extensions;
+///
+/// Provides Extensions for .
+///
public static class DateTimeExtensions
{
///
@@ -18,6 +21,7 @@ public static class DateTimeExtensions
Hour,
Minute,
Second,
+ Millisecond,
}
///
@@ -35,32 +39,15 @@ public static class DateTimeExtensions
/// The level to truncate the date to.
/// The truncated date.
public static DateTime TruncateTo(this DateTime dt, DateTruncate truncateTo)
- {
- if (truncateTo == DateTruncate.Year)
+ => truncateTo switch
{
- return new DateTime(dt.Year, 1, 1, 0, 0, 0, dt.Kind);
- }
-
- if (truncateTo == DateTruncate.Month)
- {
- return new DateTime(dt.Year, dt.Month, 1, 0, 0, 0, dt.Kind);
- }
-
- if (truncateTo == DateTruncate.Day)
- {
- return new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, dt.Kind);
- }
-
- if (truncateTo == DateTruncate.Hour)
- {
- return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0, dt.Kind);
- }
-
- if (truncateTo == DateTruncate.Minute)
- {
- return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0, dt.Kind);
- }
-
- return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Kind);
- }
+ DateTruncate.Year => new DateTime(dt.Year, 1, 1, 0, 0, 0, dt.Kind),
+ DateTruncate.Month => new DateTime(dt.Year, dt.Month, 1, 0, 0, 0, dt.Kind),
+ DateTruncate.Day => new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, dt.Kind),
+ DateTruncate.Hour => new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0, dt.Kind),
+ DateTruncate.Minute => new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0, dt.Kind),
+ DateTruncate.Second => new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Kind),
+ DateTruncate.Millisecond => new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Millisecond, dt.Kind),
+ _ => throw new ArgumentOutOfRangeException(nameof(truncateTo), truncateTo, "Invalid truncation level"),
+ };
}
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs
index b760d94c29..589c4a3516 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs
@@ -569,7 +569,7 @@ public partial class ContentEditingServiceTests
}
[Test]
- public async Task Updating_Single_Variant_Name_Does_Not_Change_Update_Dates_Of_Other_Vaiants()
+ public async Task Updating_Single_Variant_Name_Does_Not_Change_Update_Dates_Of_Other_Variants()
{
var contentType = await CreateVariantContentType(variantTitleAsMandatory: false);
@@ -614,11 +614,11 @@ public partial class ContentEditingServiceTests
void VerifyUpdate(IContent? updatedContent)
{
Assert.IsNotNull(updatedContent);
- Assert.AreEqual(firstUpdateDateDa, updatedContent.GetUpdateDate("da-DK"));
+ Assert.AreEqual(firstUpdateDateDa?.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond), updatedContent.GetUpdateDate("da-DK")?.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond));
var lastUpdateDateEn = updatedContent.GetUpdateDate("en-US")
?? throw new InvalidOperationException("Expected a publish date for EN");
- Assert.Greater(lastUpdateDateEn, firstUpdateDateEn);
+ Assert.Greater(lastUpdateDateEn.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond), firstUpdateDateEn?.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond));
}
}
@@ -671,11 +671,11 @@ public partial class ContentEditingServiceTests
void VerifyUpdate(IContent? updatedContent)
{
Assert.IsNotNull(updatedContent);
- Assert.AreEqual(firstUpdateDateEn, updatedContent.GetUpdateDate("en-US"));
+ Assert.AreEqual(firstUpdateDateEn.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond), updatedContent.GetUpdateDate("en-US")?.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond));
var lastUpdateDateDa = updatedContent.GetUpdateDate("da-DK")
?? throw new InvalidOperationException("Expected an update date for DA");
- Assert.Greater(lastUpdateDateDa, firstUpdateDateDa);
+ Assert.Greater(lastUpdateDateDa.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond), firstUpdateDateDa.TruncateTo(DateTimeExtensions.DateTruncate.Millisecond));
}
}
}
diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/DateTimeExtensionsTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/DateTimeExtensionsTests.cs
new file mode 100644
index 0000000000..deffcfa7ca
--- /dev/null
+++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/DateTimeExtensionsTests.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Umbraco.
+// See LICENSE for more details.
+
+using NUnit.Framework;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Extensions;
+
+[TestFixture]
+public class DateTimeExtensionsTests
+{
+ [Test]
+ public void ToIsoString_ReturnsCorrectFormat()
+ {
+ var date = new DateTime(2025, 6, 9, 14, 30, 45, DateTimeKind.Utc);
+ var result = date.ToIsoString();
+ Assert.AreEqual("2025-06-09 14:30:45", result);
+ }
+
+ [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Year, 2023, 1, 1, 0, 0, 0, 0)]
+ [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Month, 2023, 5, 1, 0, 0, 0, 0)]
+ [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Day, 2023, 5, 15, 0, 0, 0, 0)]
+ [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Hour, 2023, 5, 15, 14, 0, 0, 0)]
+ [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Minute, 2023, 5, 15, 14, 30, 0, 0)]
+ [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Second, 2023, 5, 15, 14, 30, 45, 0)]
+ [TestCase(2023, 5, 15, 14, 30, 45, 123, DateTimeExtensions.DateTruncate.Millisecond, 2023, 5, 15, 14, 30, 45, 123)]
+ public void TruncateTo_TruncatesCorrectly(
+ int year,
+ int month,
+ int day,
+ int hour,
+ int minute,
+ int second,
+ int millisecond,
+ DateTimeExtensions.DateTruncate truncateTo,
+ int expectedYear,
+ int expectedMonth,
+ int expectedDay,
+ int expectedHour,
+ int expectedMinute,
+ int expectedSecond,
+ int expectedMillisecond)
+ {
+ var date = new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc);
+ var expected = new DateTime(expectedYear, expectedMonth, expectedDay, expectedHour, expectedMinute, expectedSecond, expectedMillisecond, DateTimeKind.Utc);
+
+ var result = date.TruncateTo(truncateTo);
+
+ Assert.AreEqual(expected, result);
+ }
+}