Skip to content

Commit edbc144

Browse files
authored
fix (#96): improve datetime parsing on sql server (#103)
1 parent 012dd73 commit edbc144

File tree

12 files changed

+234
-83
lines changed

12 files changed

+234
-83
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,4 +354,8 @@ nuget.exe
354354
coverage.xml
355355
coverage/
356356

357-
.nuke/temp/
357+
# Nuke working files
358+
.nuke/temp/
359+
360+
# JetBrains IDE user folders
361+
.idea/

Directory.Build.props

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@
55
<PrivateAssets>all</PrivateAssets>
66
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
77
</PackageReference>
8+
<PackageReference Include="Teronis.MSBuild.Packaging.ProjectBuildInPackage" Version="1.0.0">
9+
<PrivateAssets>all</PrivateAssets>
10+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
11+
</PackageReference>
812
</ItemGroup>
913
</Project>
Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,35 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22

3-
<PropertyGroup>
4-
<TargetFramework>net7.0</TargetFramework>
5-
<UserSecretsId>aspnet-SampleWebApp-93B544DE-DDCF-47C1-AD8A-BC87C4D6B954</UserSecretsId>
6-
</PropertyGroup>
3+
<PropertyGroup>
4+
<TargetFramework>net7.0</TargetFramework>
5+
<UserSecretsId>aspnet-SampleWebApp-93B544DE-DDCF-47C1-AD8A-BC87C4D6B954</UserSecretsId>
6+
</PropertyGroup>
77

8-
<ItemGroup>
9-
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.10" />
10-
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.10" />
11-
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.10" />
12-
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="7.0.10" />
13-
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.10" />
14-
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
15-
<PrivateAssets>all</PrivateAssets>
16-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
17-
</PackageReference>
18-
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
19-
<PackageReference Include="Serilog.Formatting.Elasticsearch" Version="8.4.1" />
20-
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.1" />
21-
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
22-
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.4.1" />
23-
<PackageReference Include="Serilog.Sinks.MSSqlServer" Version="6.3.0" />
24-
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
25-
</ItemGroup>
8+
<ItemGroup>
9+
<AssemblyAttribute Include="System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute"/>
10+
</ItemGroup>
11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.10"/>
13+
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.10"/>
14+
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.10"/>
15+
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="7.0.10"/>
16+
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.10"/>
17+
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
18+
<PrivateAssets>all</PrivateAssets>
19+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
20+
</PackageReference>
21+
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0"/>
22+
<PackageReference Include="Serilog.Formatting.Elasticsearch" Version="8.4.1"/>
23+
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.1"/>
24+
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0"/>
25+
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.4.1"/>
26+
<PackageReference Include="Serilog.Sinks.MSSqlServer" Version="6.3.0"/>
27+
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0"/>
28+
</ItemGroup>
2629

27-
<ItemGroup>
28-
<ProjectReference Include="..\..\src\Serilog.Ui.MsSqlServerProvider\Serilog.Ui.MsSqlServerProvider.csproj" />
29-
<ProjectReference Include="..\..\src\Serilog.Ui.Web\Serilog.Ui.Web.csproj" />
30-
</ItemGroup>
30+
<ItemGroup>
31+
<ProjectReference Include="..\..\src\Serilog.Ui.MsSqlServerProvider\Serilog.Ui.MsSqlServerProvider.csproj"/>
32+
<ProjectReference Include="..\..\src\Serilog.Ui.Web\Serilog.Ui.Web.csproj"/>
33+
</ItemGroup>
3134

3235
</Project>

src/Serilog.Ui.MsSqlServerProvider/DapperDateTimeHandler.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Dapper;
1+
#nullable enable
2+
using Dapper;
23
using System;
34
using System.Data;
45
using System.Globalization;
@@ -7,7 +8,15 @@ namespace Serilog.Ui.MsSqlServerProvider;
78

89
public class DapperDateTimeHandler : SqlMapper.TypeHandler<DateTime>
910
{
10-
private static readonly string[] Formats = new[] {
11+
private readonly Func<string, DateTime>? _dateTimeCustomParsing;
12+
13+
public DapperDateTimeHandler(Func<string, DateTime>? dateTimeCustomParsing = null)
14+
{
15+
_dateTimeCustomParsing = dateTimeCustomParsing;
16+
}
17+
18+
private static readonly string[] Formats = new[]
19+
{
1120
"M/d/yyyy h:mm:ss tt zzz",
1221
"M/dd/yyyy h:mm:ss tt zzz",
1322
"M/d/yyyy h:mm:ss tt",
@@ -27,11 +36,24 @@ public override void SetValue(IDbDataParameter parameter, DateTime value)
2736
public override DateTime Parse(object value)
2837
{
2938
var valueStr = value.ToString();
30-
DateTime.TryParse(valueStr, CultureInfo.InvariantCulture, DateTimeStyles.None, out var timeStamp);
39+
40+
if (_dateTimeCustomParsing is not null) return CustomParse(valueStr);
41+
42+
DateTime.TryParse(valueStr, CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal, out var timeStamp);
3143

3244
if (timeStamp == default)
3345
DateTime.TryParseExact(valueStr, Formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out timeStamp);
3446

35-
return timeStamp;
47+
return timeStamp.ToUniversalTime();
48+
}
49+
50+
private DateTime CustomParse(string value)
51+
{
52+
var parseDatetime = _dateTimeCustomParsing!(value);
53+
54+
if (parseDatetime.Kind != DateTimeKind.Utc)
55+
throw new InvalidOperationException($"The parsed date must have kind: {DateTimeKind.Utc}");
56+
57+
return parseDatetime;
3658
}
3759
}

src/Serilog.Ui.MsSqlServerProvider/Extensions/SerilogUiOptionBuilderExtensions.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using Microsoft.Extensions.DependencyInjection;
22
using Serilog.Ui.Core;
33
using System;
4+
using Dapper;
45

56
namespace Serilog.Ui.MsSqlServerProvider
7+
#nullable enable
68
{
79
/// <summary>
810
/// SQL Server data provider specific extension methods for <see cref="SerilogUiOptionsBuilder"/>.
@@ -18,13 +20,18 @@ public static class SerilogUiOptionBuilderExtensions
1820
/// <param name="schemaName">
1921
/// Name of the table schema. default value is <c> dbo </c>
2022
/// </param>
23+
/// <param name="dateTimeCustomParsing">
24+
/// Delegate to customize the DateTime parsing.
25+
/// It throws <see cref="InvalidOperationException" /> if the return DateTime isn't UTC kind.
26+
/// </param>
2127
/// <exception cref="ArgumentNullException"> throw if connectionString is null </exception>
2228
/// <exception cref="ArgumentNullException"> throw is tableName is null </exception>
2329
public static SerilogUiOptionsBuilder UseSqlServer(
2430
this SerilogUiOptionsBuilder optionsBuilder,
2531
string connectionString,
2632
string tableName,
27-
string schemaName = "dbo"
33+
string schemaName = "dbo",
34+
Func<string, DateTime>? dateTimeCustomParsing = null
2835
)
2936
{
3037
if (string.IsNullOrWhiteSpace(connectionString))
@@ -40,9 +47,12 @@ public static SerilogUiOptionsBuilder UseSqlServer(
4047
Schema = !string.IsNullOrWhiteSpace(schemaName) ? schemaName : "dbo"
4148
};
4249

43-
((ISerilogUiOptionsBuilder)optionsBuilder).Services
44-
.AddScoped<IDataProvider, SqlServerDataProvider>(p => ActivatorUtilities.CreateInstance<SqlServerDataProvider>(p, relationProvider));
45-
50+
SqlMapper.AddTypeHandler(new DapperDateTimeHandler(dateTimeCustomParsing));
51+
52+
((ISerilogUiOptionsBuilder) optionsBuilder).Services
53+
.AddScoped<IDataProvider, SqlServerDataProvider>(p =>
54+
ActivatorUtilities.CreateInstance<SqlServerDataProvider>(p, relationProvider));
55+
4656
return optionsBuilder;
4757
}
4858
}

src/Serilog.Ui.MsSqlServerProvider/Serilog.Ui.MsSqlServerProvider.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<LangVersion>latest</LangVersion>
6-
<Version>2.2.2</Version>
6+
<Version>2.2.3</Version>
77
</PropertyGroup>
88

99
<ItemGroup>
@@ -12,6 +12,6 @@
1212
</ItemGroup>
1313

1414
<ItemGroup>
15-
<ProjectReference Include="..\Serilog.Ui.Core\Serilog.Ui.Core.csproj" />
15+
<ProjectReference Include="..\Serilog.Ui.Core\Serilog.Ui.Core.csproj" PrivateAssets="All" />
1616
</ItemGroup>
1717
</Project>

src/Serilog.Ui.MsSqlServerProvider/SqlServerDataProvider.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ public SqlServerDataProvider(RelationalDbOptions options)
1818
_options = options ?? throw new ArgumentNullException(nameof(options));
1919
}
2020

21-
static SqlServerDataProvider()
22-
{
23-
SqlMapper.AddTypeHandler(new DapperDateTimeHandler());
24-
}
25-
2621
public string Name => _options.ToDataProviderName("MsSQL");
2722

2823
public async Task<(IEnumerable<LogModel>, int)> FetchDataAsync(

src/Serilog.Ui.Web/package-lock.json

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Serilog.Ui.Web/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
"test:ci": "jest --ci --reporters=default --reporters=jest-junit"
1313
},
1414
"devDependencies": {
15-
"@testing-library/dom": "^9.2.0",
15+
"@testing-library/dom": "^9.3.4",
1616
"@testing-library/jest-dom": "^5.16.5",
1717
"@testing-library/user-event": "^14.4.3",
1818
"@types/bootstrap": "^5.2.6",
1919
"@types/jest": "^29.5.1",
2020
"@types/jquery": "^3.5.16",
2121
"@types/jsdom": "^21.1.1",
22-
"@types/node": "^18.16.1",
22+
"@types/node": "^20.11.0",
2323
"@types/parcel-bundler": "^1.12.5",
2424
"grunt": "^1.6.1",
2525
"grunt-contrib-clean": "^2.0.1",
@@ -37,7 +37,7 @@
3737
"whatwg-fetch": "^3.6.2"
3838
},
3939
"dependencies": {
40-
"@fortawesome/fontawesome-free": "6.4.0",
40+
"@fortawesome/fontawesome-free": "^6.5.1",
4141
"bootstrap": "4.5.3",
4242
"date-fns": "^2.29.3",
4343
"jquery": "^3.6.4",

tests/Directory.Build.props

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
<Project>
2-
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
3-
4-
<ItemGroup>
5-
<PackageReference Include="FluentAssertions" Version="6.12.0" />
6-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
7-
<PackageReference Include="NSubstitute" Version="5.0.0" />
8-
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.16">
9-
<PrivateAssets>all</PrivateAssets>
10-
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
11-
</PackageReference>
12-
<PackageReference Include="Testcontainers" Version="3.4.0" />
13-
<PackageReference Include="xunit" Version="2.5.0" />
14-
<PackageReference Include="xunit.extensibility.core" Version="2.5.0" />
15-
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0">
16-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
17-
<PrivateAssets>all</PrivateAssets>
18-
</PackageReference>
19-
<PackageReference Include="coverlet.collector" Version="6.0.0">
20-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
21-
<PrivateAssets>all</PrivateAssets>
22-
</PackageReference>
23-
</ItemGroup>
2+
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))"/>
3+
<ItemGroup>
4+
<AssemblyAttribute Include="System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute"/>
5+
</ItemGroup>
6+
<ItemGroup>
7+
<PackageReference Include="FluentAssertions" Version="6.12.0"/>
8+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2"/>
9+
<PackageReference Include="NSubstitute" Version="5.0.0"/>
10+
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.16">
11+
<PrivateAssets>all</PrivateAssets>
12+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
13+
</PackageReference>
14+
<PackageReference Include="Testcontainers" Version="3.4.0"/>
15+
<PackageReference Include="xunit" Version="2.5.0"/>
16+
<PackageReference Include="xunit.extensibility.core" Version="2.5.0"/>
17+
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0">
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
<PrivateAssets>all</PrivateAssets>
20+
</PackageReference>
21+
<PackageReference Include="coverlet.collector" Version="6.0.0">
22+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
23+
<PrivateAssets>all</PrivateAssets>
24+
</PackageReference>
25+
</ItemGroup>
2426
</Project>

tests/Serilog.Ui.Common.Tests/Serilog.Ui.Common.Tests.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
<PackageReference Include="Serilog" Version="3.0.1" />
1515
</ItemGroup>
1616

17-
<ItemGroup>
18-
<AssemblyAttribute Include="System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute" />
19-
</ItemGroup>
20-
2117
<ItemGroup>
2218
<ProjectReference Include="..\..\src\Serilog.Ui.Core\Serilog.Ui.Core.csproj" />
2319
<ProjectReference Include="..\..\src\Serilog.Ui.MongoDbProvider\Serilog.Ui.MongoDbProvider.csproj" />

0 commit comments

Comments
 (0)