diff --git a/Serilog.sln.DotSettings b/Serilog.sln.DotSettings index 163ba67c0..d98a03dac 100644 --- a/Serilog.sln.DotSettings +++ b/Serilog.sln.DotSettings @@ -195,6 +195,7 @@ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True True True True diff --git a/src/Serilog/Capturing/PropertyValueConverter.cs b/src/Serilog/Capturing/PropertyValueConverter.cs index 012e193fa..cb2e76c0c 100644 --- a/src/Serilog/Capturing/PropertyValueConverter.cs +++ b/src/Serilog/Capturing/PropertyValueConverter.cs @@ -42,7 +42,10 @@ partial class PropertyValueConverter : ILogEventPropertyFactory, ILogEventProper typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(string), typeof(DateTime), typeof(DateTimeOffset), typeof(TimeSpan), - typeof(Guid), typeof(Uri) + typeof(Guid), typeof(Uri), + #if FEATURE_DATE_AND_TIME_ONLY + typeof(TimeOnly), typeof(DateOnly) + #endif }; readonly IDestructuringPolicy[] _destructuringPolicies; diff --git a/src/Serilog/Formatting/Json/JsonFormatter.cs b/src/Serilog/Formatting/Json/JsonFormatter.cs index 0adaade7e..6d02d5b59 100644 --- a/src/Serilog/Formatting/Json/JsonFormatter.cs +++ b/src/Serilog/Formatting/Json/JsonFormatter.cs @@ -103,6 +103,10 @@ public JsonFormatter( { typeof(string), (v, _, w) => WriteString((string)v, w) }, { typeof(DateTime), (v, _, w) => WriteDateTime((DateTime)v, w) }, { typeof(DateTimeOffset), (v, _, w) => WriteOffset((DateTimeOffset)v, w) }, +#if FEATURE_DATE_AND_TIME_ONLY + { typeof(DateOnly), (v, _, w) => WriteDateOnly((DateOnly)v, w) }, + { typeof(TimeOnly), (v, _, w) => WriteTimeOnly((TimeOnly)v, w) }, +#endif { typeof(ScalarValue), (v, q, w) => WriteLiteral(((ScalarValue)v).Value, w, q) }, { typeof(SequenceValue), (v, _, w) => WriteSequence(((SequenceValue)v).Elements, w) }, { typeof(DictionaryValue), (v, _, w) => WriteDictionary(((DictionaryValue)v).Elements, w) }, @@ -429,6 +433,24 @@ static void WriteDateTime(DateTime value, TextWriter output) output.Write("\""); } +#if FEATURE_DATE_AND_TIME_ONLY + + static void WriteDateOnly(DateOnly value, TextWriter output) + { + output.Write("\""); + output.Write(value.ToString("yyyy-MM-dd")); + output.Write("\""); + } + + static void WriteTimeOnly(TimeOnly value, TextWriter output) + { + output.Write("\""); + output.Write(value.ToString("O")); + output.Write("\""); + } + +#endif + static void WriteString(string value, TextWriter output) { JsonValueFormatter.WriteQuotedJsonString(value, output); diff --git a/src/Serilog/Formatting/Json/JsonValueFormatter.cs b/src/Serilog/Formatting/Json/JsonValueFormatter.cs index 0a5a2a37d..6f6c03296 100644 --- a/src/Serilog/Formatting/Json/JsonValueFormatter.cs +++ b/src/Serilog/Formatting/Json/JsonValueFormatter.cs @@ -219,6 +219,20 @@ protected virtual void FormatLiteralValue(object value, TextWriter output) FormatTimeSpanValue(timeSpan, output); return; } + +#if FEATURE_DATE_AND_TIME_ONLY + if (value is DateOnly dateOnly) + { + FormatDateOnlyValue(dateOnly, output); + return; + } + + if (value is TimeOnly timeOnly) + { + FormatTimeOnlyValue(timeOnly, output); + return; + } +#endif } FormatLiteralObjectValue(value, output); @@ -270,6 +284,24 @@ static void FormatTimeSpanValue(TimeSpan value, TextWriter output) output.Write('\"'); } +#if FEATURE_DATE_AND_TIME_ONLY + + static void FormatDateOnlyValue(DateOnly value, TextWriter output) + { + output.Write('\"'); + output.Write(value.ToString("yyyy-MM-dd")); + output.Write('\"'); + } + + static void FormatTimeOnlyValue(TimeOnly value, TextWriter output) + { + output.Write('\"'); + output.Write(value.ToString("O")); + output.Write('\"'); + } + +#endif + static void FormatLiteralObjectValue(object value, TextWriter output) { if (value == null) throw new ArgumentNullException(nameof(value)); diff --git a/src/Serilog/Serilog.csproj b/src/Serilog/Serilog.csproj index 9190ee3a9..b25850e11 100644 --- a/src/Serilog/Serilog.csproj +++ b/src/Serilog/Serilog.csproj @@ -46,7 +46,7 @@ - $(DefineConstants);ASYNCLOCAL;HASHTABLE;FEATURE_DEFAULT_INTERFACE;FEATURE_SPAN + $(DefineConstants);ASYNCLOCAL;HASHTABLE;FEATURE_DEFAULT_INTERFACE;FEATURE_SPAN;FEATURE_DATE_AND_TIME_ONLY diff --git a/test/Serilog.Tests/Formatting/Json/JsonFormatterTests.cs b/test/Serilog.Tests/Formatting/Json/JsonFormatterTests.cs index ad69eed04..74091ab3b 100644 --- a/test/Serilog.Tests/Formatting/Json/JsonFormatterTests.cs +++ b/test/Serilog.Tests/Formatting/Json/JsonFormatterTests.cs @@ -31,6 +31,42 @@ public void JsonFormattedEventsIncludeTimestamp() (string)formatted.Timestamp); } +#if FEATURE_DATE_AND_TIME_ONLY + + [Fact] + public void JsonFormattedDateOnly() + { + var @event = new LogEvent( + DateTimeOffset.MaxValue, + LogEventLevel.Information, + null, + Some.MessageTemplate(), + new[] {new LogEventProperty("name", new ScalarValue(DateOnly.MaxValue))}); + + var formatted = FormatJson(@event); + Assert.Equal( + "9999-12-31", + (string) formatted.Properties.name); + } + + [Fact] + public void JsonFormattedTimeOnly() + { + var @event = new LogEvent( + DateTimeOffset.MaxValue, + LogEventLevel.Information, + null, + Some.MessageTemplate(), + new[] {new LogEventProperty("name", new ScalarValue(TimeOnly.MaxValue))}); + + var formatted = FormatJson(@event); + Assert.Equal( + "23:59:59.9999999", + (string) formatted.Properties.name); + } + +#endif + static string FormatToJson(LogEvent @event) { var formatter = new JsonFormatter(); diff --git a/test/Serilog.Tests/Formatting/Json/JsonValueFormatterTests.cs b/test/Serilog.Tests/Formatting/Json/JsonValueFormatterTests.cs index b27666f24..e41742d48 100644 --- a/test/Serilog.Tests/Formatting/Json/JsonValueFormatterTests.cs +++ b/test/Serilog.Tests/Formatting/Json/JsonValueFormatterTests.cs @@ -51,6 +51,22 @@ public void DateTimesFormatAsIso8601() JsonLiteralTypesAreFormatted(new DateTime(2016, 01, 01, 13, 13, 13, DateTimeKind.Utc), "\"2016-01-01T13:13:13.0000000Z\""); } +#if FEATURE_DATE_AND_TIME_ONLY + + [Fact] + public void DateOnly() + { + JsonLiteralTypesAreFormatted(new DateOnly(2016, 01, 01), "\"2016-01-01\""); + } + + [Fact] + public void TimeOnly() + { + JsonLiteralTypesAreFormatted(new TimeOnly(13, 01, 01, 999), "\"13:01:01.9990000\""); + } + +#endif + [Fact] public void DoubleFormatsAsNumber() { diff --git a/test/Serilog.Tests/Serilog.Tests.csproj b/test/Serilog.Tests/Serilog.Tests.csproj index 9bdbe0227..fbee0eb92 100644 --- a/test/Serilog.Tests/Serilog.Tests.csproj +++ b/test/Serilog.Tests/Serilog.Tests.csproj @@ -40,6 +40,6 @@ $(DefineConstants);ASYNCLOCAL;FEATURE_DEFAULT_INTERFACE;FEATURE_SPAN - $(DefineConstants);ASYNCLOCAL;FEATURE_DEFAULT_INTERFACE;FEATURE_SPAN + $(DefineConstants);ASYNCLOCAL;FEATURE_DEFAULT_INTERFACE;FEATURE_SPAN;FEATURE_DATE_AND_TIME_ONLY