diff --git a/src/Logging.XUnit.v3/PublicAPI/net8.0/PublicAPI.Shipped.txt b/src/Logging.XUnit.v3/PublicAPI/net8.0/PublicAPI.Shipped.txt
new file mode 100644
index 00000000..7dc5c581
--- /dev/null
+++ b/src/Logging.XUnit.v3/PublicAPI/net8.0/PublicAPI.Shipped.txt
@@ -0,0 +1 @@
+#nullable enable
diff --git a/src/Logging.XUnit.v3/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/Logging.XUnit.v3/PublicAPI/net8.0/PublicAPI.Unshipped.txt
new file mode 100644
index 00000000..3c8006fb
--- /dev/null
+++ b/src/Logging.XUnit.v3/PublicAPI/net8.0/PublicAPI.Unshipped.txt
@@ -0,0 +1,3 @@
+#nullable enable
+MartinCostello.Logging.XUnit.XUnitLoggerOptions.TimeProvider.get -> System.TimeProvider!
+MartinCostello.Logging.XUnit.XUnitLoggerOptions.TimeProvider.set -> void
diff --git a/src/Logging.XUnit/PublicAPI/net8.0/PublicAPI.Shipped.txt b/src/Logging.XUnit/PublicAPI/net8.0/PublicAPI.Shipped.txt
new file mode 100644
index 00000000..7dc5c581
--- /dev/null
+++ b/src/Logging.XUnit/PublicAPI/net8.0/PublicAPI.Shipped.txt
@@ -0,0 +1 @@
+#nullable enable
diff --git a/src/Logging.XUnit/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/Logging.XUnit/PublicAPI/net8.0/PublicAPI.Unshipped.txt
new file mode 100644
index 00000000..3c8006fb
--- /dev/null
+++ b/src/Logging.XUnit/PublicAPI/net8.0/PublicAPI.Unshipped.txt
@@ -0,0 +1,3 @@
+#nullable enable
+MartinCostello.Logging.XUnit.XUnitLoggerOptions.TimeProvider.get -> System.TimeProvider!
+MartinCostello.Logging.XUnit.XUnitLoggerOptions.TimeProvider.set -> void
diff --git a/src/Shared/XUnitLogger.cs b/src/Shared/XUnitLogger.cs
index 90c6df8b..e877a833 100644
--- a/src/Shared/XUnitLogger.cs
+++ b/src/Shared/XUnitLogger.cs
@@ -39,6 +39,15 @@ public partial class XUnitLogger : ILogger
///
private readonly string _timestampFormat;
+#if NET8_0_OR_GREATER
+
+ ///
+ /// The time provider used in log messages.
+ ///
+ private readonly TimeProvider _timeProvider;
+
+#endif
+
///
/// Gets or sets the filter to use.
///
@@ -57,6 +66,12 @@ private XUnitLogger(string name, XUnitLoggerOptions? options)
_messageSinkMessageFactory = options?.MessageSinkMessageFactory ?? (static (message) => new DiagnosticMessage(message));
_timestampFormat = options?.TimestampFormat ?? "u";
IncludeScopes = options?.IncludeScopes ?? false;
+#if NET8_0_OR_GREATER
+ _timeProvider = options?.TimeProvider ?? TimeProvider.System;
+ Clock = () => _timeProvider.GetLocalNow();
+#else
+ Clock = static () => DateTimeOffset.Now;
+#endif
}
///
@@ -84,7 +99,7 @@ private XUnitLogger(string name, XUnitLoggerOptions? options)
///
/// Gets or sets a delegate representing the system clock.
///
- internal Func Clock { get; set; } = static () => DateTimeOffset.Now;
+ internal Func Clock { get; set; }
///
public IDisposable? BeginScope(TState state)
diff --git a/src/Shared/XUnitLoggerOptions.cs b/src/Shared/XUnitLoggerOptions.cs
index db397713..1282cbd6 100644
--- a/src/Shared/XUnitLoggerOptions.cs
+++ b/src/Shared/XUnitLoggerOptions.cs
@@ -38,4 +38,13 @@ public XUnitLoggerOptions()
///
[StringSyntax(StringSyntaxAttribute.DateTimeFormat)]
public string? TimestampFormat { get; set; }
+
+#if NET8_0_OR_GREATER
+
+ ///
+ /// Gets or sets the time provider used in log messages. Defaults to .
+ ///
+ public TimeProvider TimeProvider { get; set; } = TimeProvider.System;
+
+#endif
}
diff --git a/tests/Shared/XUnitLoggerTests.cs b/tests/Shared/XUnitLoggerTests.cs
index 165232ec..1efde1e4 100644
--- a/tests/Shared/XUnitLoggerTests.cs
+++ b/tests/Shared/XUnitLoggerTests.cs
@@ -659,6 +659,41 @@ public static void XUnitLogger_Log_Logs_Message_If_Scopes_Included_And_There_Is_
outputHelper.Received(1).WriteLine(expected);
}
+#if NET8_0_OR_GREATER
+
+ [Fact]
+ public static void XUnitLogger_Log_Logs_Message_With_TimeProvider()
+ {
+ // Arrange
+ var outputHelper = Substitute.For();
+ string name = "MyName";
+
+ var timeProvider = Substitute.For();
+ timeProvider.LocalTimeZone.Returns(TimeZoneInfo.FindSystemTimeZoneById("Europe/London"));
+ timeProvider.GetUtcNow().Returns(new DateTimeOffset(2019, 05, 12, 13, 47, 41, 123, 456, TimeSpan.Zero));
+
+ var options = new XUnitLoggerOptions()
+ {
+ Filter = FilterTrue,
+ TimeProvider = timeProvider,
+ };
+
+ var logger = new XUnitLogger(name, outputHelper, options);
+
+ string expected = string.Join(
+ Environment.NewLine,
+ "[2019-05-12 13:47:41Z] info: MyName[85]",
+ " Message|True|False");
+
+ // Act
+ logger.Log(LogLevel.Information, new EventId(85), "Martin", null, Formatter);
+
+ // Assert
+ outputHelper.Received(1).WriteLine(expected);
+ }
+
+#endif
+
private static DateTimeOffset StaticClock() => new(2018, 08, 19, 17, 12, 16, TimeSpan.FromHours(1));
private static DiagnosticMessage DiagnosticMessageFactory(string message) => new(message);