From 5e3fff446e712425b7d0d236c8ff6102679a1ffe Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 1 Mar 2025 10:28:04 +0800 Subject: [PATCH] Add DateTimeOffset conversion method to IClock and only normalizing DateTime in MVC. --- .../AbpAspNetCoreMvcNewtonsoftModule.cs | 4 +- .../Mvc/Json/MvcCoreBuilderExtensions.cs | 8 +++ .../ClientProxyRequestPayloadBuilder.cs | 28 ++++++++-- .../ClientProxying/ClientProxyUrlBuilder.cs | 21 ++++++-- .../Json/Newtonsoft/AbpDateTimeConverter.cs | 22 ++++++-- .../Newtonsoft/AbpJsonNewtonsoftModule.cs | 3 +- .../Newtonsoft/AbpNewtonsoftJsonSerializer.cs | 3 +- .../AbpJsonSystemTextJsonModule.cs | 13 +++-- .../JsonConverters/AbpDateTimeConverter.cs | 22 ++++++-- .../AbpNullableDateTimeConverter.cs | 22 ++++++-- .../Volo.Abp.Timing/Volo/Abp/Timing/Clock.cs | 12 +++++ .../Volo.Abp.Timing/Volo/Abp/Timing/IClock.cs | 7 +++ .../Abp/Json/AbpJsonNewtonsoftTestModule.cs | 26 --------- ...TextJsonTestBase.cs => AbpJsonTestBase.cs} | 0 .../Volo/Abp/Json/AbpJsonTestModule.cs | 53 +++++++++++++++++++ 15 files changed, 186 insertions(+), 58 deletions(-) delete mode 100644 framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonNewtonsoftTestModule.cs rename framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/{AbpJsonSystemTextJsonTestBase.cs => AbpJsonTestBase.cs} (100%) create mode 100644 framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs index d213c9f451..95e07a06e0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs @@ -16,7 +16,9 @@ public class AbpAspNetCoreMvcNewtonsoftModule : AbpModule context.Services.AddOptions() .Configure((options, rootServiceProvider) => { - options.SerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver(rootServiceProvider.GetRequiredService()); + options.SerializerSettings.ContractResolver = + new AbpCamelCasePropertyNamesContractResolver(rootServiceProvider + .GetRequiredService()); }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs index 8c6edd2eb0..f2bac81316 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Json.SystemTextJson.JsonConverters; +using Volo.Abp.Json.SystemTextJson.Modifiers; namespace Volo.Abp.AspNetCore.Mvc.Json; @@ -26,6 +27,13 @@ public static class MvcCoreBuilderExtensions options.JsonSerializerOptions.TypeInfoResolver = new AbpDefaultJsonTypeInfoResolver(rootServiceProvider .GetRequiredService>()); + + var dateTimeConverter = rootServiceProvider.GetRequiredService(); + var nullableDateTimeConverter = rootServiceProvider.GetRequiredService(); + + options.JsonSerializerOptions.TypeInfoResolver.As().Modifiers.Add( + new AbpDateTimeConverterModifier(dateTimeConverter, nullableDateTimeConverter) + .CreateModifyAction()); }); return builder; diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs index c24404918e..91fc6f33bf 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs @@ -15,6 +15,7 @@ using Volo.Abp.Http.Client.Proxying; using Volo.Abp.Http.Modeling; using Volo.Abp.Http.ProxyScripting.Generators; using Volo.Abp.Json; +using Volo.Abp.Timing; namespace Volo.Abp.Http.Client.ClientProxying; @@ -33,9 +34,15 @@ public class ClientProxyRequestPayloadBuilder : ITransientDependency protected AbpHttpClientProxyingOptions HttpClientProxyingOptions { get; } - public ClientProxyRequestPayloadBuilder(IServiceScopeFactory serviceScopeFactory, IOptions httpClientProxyingOptions) + protected IClock Clock { get; } + + public ClientProxyRequestPayloadBuilder( + IServiceScopeFactory serviceScopeFactory, + IOptions httpClientProxyingOptions, + IClock clock) { ServiceScopeFactory = serviceScopeFactory; + Clock = clock; HttpClientProxyingOptions = httpClientProxyingOptions.Value; } @@ -156,12 +163,12 @@ public class ClientProxyRequestPayloadBuilder : ITransientDependency { foreach (var item in (IEnumerable) value) { - formData.Add(new StringContent(item.ToString()!, Encoding.UTF8), parameter.Name); + formData.Add(new StringContent(await ConvertValueToStringAsync(item), Encoding.UTF8), parameter.Name); } } else { - formData.Add(new StringContent(value.ToString()!, Encoding.UTF8), parameter.Name); + formData.Add(new StringContent(await ConvertValueToStringAsync(value), Encoding.UTF8), parameter.Name); } } @@ -172,4 +179,19 @@ public class ClientProxyRequestPayloadBuilder : ITransientDependency { return await converter.ConvertAsync(actionApiDescription, parameterApiDescription, value); } + + protected virtual Task ConvertValueToStringAsync(object value) + { + if (value is DateTime dateTimeValue) + { + if (Clock.SupportsMultipleTimezone || dateTimeValue.Kind == DateTimeKind.Utc) + { + return Task.FromResult(dateTimeValue.ToUniversalTime().ToString("O")); + } + + return Task.FromResult(dateTimeValue.ToString("yyyy-MM-ddTHH:mm:ss.fffffff").TrimEnd('0').TrimEnd('.')); + } + + return Task.FromResult(value.ToString()!); + } } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs index 65703dc56b..5be598af20 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs @@ -14,6 +14,7 @@ using Volo.Abp.Http.Client.Proxying; using Volo.Abp.Http.Modeling; using Volo.Abp.Http.ProxyScripting.Generators; using Volo.Abp.Localization; +using Volo.Abp.Timing; namespace Volo.Abp.Http.Client.ClientProxying; @@ -36,11 +37,16 @@ public class ClientProxyUrlBuilder : ITransientDependency protected IServiceScopeFactory ServiceScopeFactory { get; } protected AbpHttpClientProxyingOptions HttpClientProxyingOptions { get; } + protected IClock Clock { get; } - public ClientProxyUrlBuilder(IServiceScopeFactory serviceScopeFactory, IOptions httpClientProxyingOptions) + public ClientProxyUrlBuilder( + IServiceScopeFactory serviceScopeFactory, + IOptions httpClientProxyingOptions, + IClock clock) { ServiceScopeFactory = serviceScopeFactory; HttpClientProxyingOptions = httpClientProxyingOptions.Value; + Clock = clock; } public async Task GenerateUrlWithParametersAsync(ActionApiDescriptionModel action, IReadOnlyDictionary methodArguments, ApiVersionInfo apiVersion) @@ -218,13 +224,18 @@ public class ClientProxyUrlBuilder : ITransientDependency return true; } - protected virtual Task ConvertValueToStringAsync(object? value) + protected virtual Task ConvertValueToStringAsync(object value) { if (value is DateTime dateTimeValue) { - return Task.FromResult(dateTimeValue.ToUniversalTime().ToString("O"))!; + if (Clock.SupportsMultipleTimezone || dateTimeValue.Kind == DateTimeKind.Utc) + { + return Task.FromResult(dateTimeValue.ToUniversalTime().ToString("O")); + } + + return Task.FromResult(dateTimeValue.ToString("yyyy-MM-ddTHH:mm:ss.fffffff").TrimEnd('0').TrimEnd('.')); } - return Task.FromResult(value?.ToString()); + return Task.FromResult(value.ToString()!); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs index effda40057..c95660e484 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs @@ -19,6 +19,7 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency private readonly CultureInfo _culture = CultureInfo.InvariantCulture; private readonly IClock _clock; private readonly AbpJsonOptions _options; + private bool _skipDateTimeNormalization; public AbpDateTimeConverter(IClock clock, IOptions options) { @@ -26,6 +27,12 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency _options = options.Value; } + public virtual AbpDateTimeConverter SkipDateTimeNormalization() + { + _skipDateTimeNormalization = true; + return this; + } + public override bool CanConvert(Type objectType) { return objectType == typeof(DateTime) || objectType == typeof(DateTime?); @@ -46,7 +53,7 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency if (reader.TokenType == JsonToken.Date) { - return _clock.Normalize(reader.Value!.To()); + return Normalize(reader.Value!.To()); } if (reader.TokenType != JsonToken.String) @@ -67,20 +74,20 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency { if (DateTime.TryParseExact(dateText, format, _culture, _dateTimeStyles, out var d1)) { - return _clock.Normalize(d1); + return Normalize(d1); } } } var date = DateTime.Parse(dateText!, _culture, _dateTimeStyles); - return _clock.Normalize(date); + return Normalize(date); } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value != null) { - value = _clock.Normalize(value.To()); + value = Normalize(value.To()); } if (value is DateTime dateTime) @@ -111,4 +118,11 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency return ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(member) == null; } + + protected virtual DateTime Normalize(DateTime dateTime) + { + return _skipDateTimeNormalization + ? dateTime + : _clock.Normalize(dateTime); + } } diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs index 6f93a6c54e..ea35831d86 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs @@ -13,7 +13,8 @@ public class AbpJsonNewtonsoftModule : AbpModule context.Services.AddOptions() .Configure((options, rootServiceProvider) => { - options.JsonSerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver(rootServiceProvider.GetRequiredService()); + options.JsonSerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver( + rootServiceProvider.GetRequiredService().SkipDateTimeNormalization()); }); } } diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs index 0450064f2f..8184ee6d45 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs @@ -86,7 +86,8 @@ public class AbpNewtonsoftJsonSerializer : IJsonSerializer, ITransientDependency if (!camelCase) { //Default contract resolver is AbpCamelCasePropertyNamesContractResolver} - settings.ContractResolver = new AbpDefaultContractResolver(RootServiceProvider.GetRequiredService()); + settings.ContractResolver = new AbpDefaultContractResolver(RootServiceProvider + .GetRequiredService().SkipDateTimeNormalization()); } if (indented) diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs index 498dedd8cd..0a5066cec1 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs @@ -29,14 +29,13 @@ public class AbpJsonSystemTextJsonModule : AbpModule options.JsonSerializerOptions.TypeInfoResolver = new AbpDefaultJsonTypeInfoResolver(rootServiceProvider .GetRequiredService>()); - }); - context.Services.AddOptions() - .Configure((options, rootServiceProvider) => - { - options.Modifiers.Add(new AbpDateTimeConverterModifier( - rootServiceProvider.GetRequiredService(), - rootServiceProvider.GetRequiredService()).CreateModifyAction()); + var dateTimeConverter = rootServiceProvider.GetRequiredService().SkipDateTimeNormalization(); + var nullableDateTimeConverter = rootServiceProvider.GetRequiredService().SkipDateTimeNormalization(); + + options.JsonSerializerOptions.TypeInfoResolver.As().Modifiers.Add( + new AbpDateTimeConverterModifier(dateTimeConverter, nullableDateTimeConverter) + .CreateModifyAction()); }); } } diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs index a8653bb54a..3feea8d299 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs @@ -13,6 +13,7 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc { private readonly IClock _clock; private readonly AbpJsonOptions _options; + private bool _skipDateTimeNormalization; public AbpDateTimeConverter(IClock clock, IOptions abpJsonOptions) { @@ -20,6 +21,12 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc _options = abpJsonOptions.Value; } + public virtual AbpDateTimeConverter SkipDateTimeNormalization() + { + _skipDateTimeNormalization = true; + return this; + } + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (_options.InputDateTimeFormats.Any()) @@ -31,7 +38,7 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc var s = reader.GetString(); if (DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1)) { - return _clock.Normalize(d1); + return Normalize(d1); } } } @@ -43,7 +50,7 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc if (reader.TryGetDateTime(out var d3)) { - return _clock.Normalize(d3); + return Normalize(d3); } var dateText = reader.GetString(); @@ -51,7 +58,7 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc { if (DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d4)) { - return _clock.Normalize(d4); + return Normalize(d4); } } @@ -62,11 +69,16 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc { if (_options.OutputDateTimeFormat.IsNullOrWhiteSpace()) { - writer.WriteStringValue(_clock.Normalize(value)); + writer.WriteStringValue(Normalize(value)); } else { - writer.WriteStringValue(_clock.Normalize(value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); + writer.WriteStringValue(Normalize(value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); } } + + protected virtual DateTime Normalize(DateTime dateTime) + { + return _skipDateTimeNormalization ? dateTime : _clock.Normalize(dateTime); + } } diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs index e8a94892da..e73f39d097 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs @@ -13,6 +13,7 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient { private readonly IClock _clock; private readonly AbpJsonOptions _options; + private bool _skipDateTimeNormalization; public AbpNullableDateTimeConverter(IClock clock, IOptions abpJsonOptions) { @@ -20,6 +21,12 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient _options = abpJsonOptions.Value; } + public virtual AbpNullableDateTimeConverter SkipDateTimeNormalization() + { + _skipDateTimeNormalization = true; + return this; + } + public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (_options.InputDateTimeFormats.Any()) @@ -31,7 +38,7 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient var s = reader.GetString(); if (DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1)) { - return _clock.Normalize(d1); + return Normalize(d1); } } } @@ -43,7 +50,7 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient if (reader.TryGetDateTime(out var d2)) { - return _clock.Normalize(d2); + return Normalize(d2); } var dateText = reader.GetString(); @@ -51,7 +58,7 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient { if (DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d3)) { - return _clock.Normalize(d3); + return Normalize(d3); } } @@ -68,12 +75,17 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient { if (_options.OutputDateTimeFormat.IsNullOrWhiteSpace()) { - writer.WriteStringValue(_clock.Normalize(value.Value)); + writer.WriteStringValue(Normalize(value.Value)); } else { - writer.WriteStringValue(_clock.Normalize(value.Value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); + writer.WriteStringValue(Normalize(value.Value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); } } } + + protected virtual DateTime Normalize(DateTime dateTime) + { + return _skipDateTimeNormalization ? dateTime : _clock.Normalize(dateTime); + } } diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Clock.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Clock.cs index 9e012ed11c..1da94b7324 100644 --- a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Clock.cs +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Clock.cs @@ -58,4 +58,16 @@ public class Clock : IClock, ITransientDependency var timezoneInfo = TimezoneProvider.GetTimeZoneInfo(CurrentTimezoneProvider.TimeZone); return TimeZoneInfo.ConvertTime(dateTime, timezoneInfo); } + + public virtual DateTimeOffset Convert(DateTimeOffset dateTimeOffset) + { + if (!SupportsMultipleTimezone || + CurrentTimezoneProvider.TimeZone.IsNullOrWhiteSpace()) + { + return dateTimeOffset; + } + + var timezoneInfo = TimezoneProvider.GetTimeZoneInfo(CurrentTimezoneProvider.TimeZone); + return TimeZoneInfo.ConvertTime(dateTimeOffset, timezoneInfo); + } } diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClock.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClock.cs index 29f16a749a..3a87726655 100644 --- a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClock.cs +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClock.cs @@ -32,4 +32,11 @@ public interface IClock /// DateTime to be normalized. /// Converted DateTime DateTime Convert(DateTime dateTime); + + /// + /// Converts given to user's time zone. + /// + /// DateTimeOffset to be normalized. + /// Converted DateTimeOffset + DateTimeOffset Convert(DateTimeOffset dateTimeOffset); } diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonNewtonsoftTestModule.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonNewtonsoftTestModule.cs deleted file mode 100644 index 42559397da..0000000000 --- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonNewtonsoftTestModule.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Volo.Abp.Autofac; -using Volo.Abp.Json.Newtonsoft; -using Volo.Abp.Json.SystemTextJson; -using Volo.Abp.Modularity; - -namespace Volo.Abp.Json; - -[DependsOn( - typeof(AbpAutofacModule), - typeof(AbpJsonSystemTextJsonModule), - typeof(AbpTestBaseModule) -)] -public class AbpJsonSystemTextJsonTestModule : AbpModule -{ - -} - -[DependsOn( - typeof(AbpAutofacModule), - typeof(AbpJsonNewtonsoftModule), - typeof(AbpTestBaseModule) -)] -public class AbpJsonNewtonsoftTestModule : AbpModule -{ - -} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonSystemTextJsonTestBase.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestBase.cs similarity index 100% rename from framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonSystemTextJsonTestBase.cs rename to framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestBase.cs diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs new file mode 100644 index 0000000000..121ec62a85 --- /dev/null +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Autofac; +using Volo.Abp.Json.Newtonsoft; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Json.SystemTextJson.JsonConverters; +using Volo.Abp.Json.SystemTextJson.Modifiers; +using Volo.Abp.Modularity; + +namespace Volo.Abp.Json; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpJsonSystemTextJsonModule), + typeof(AbpTestBaseModule) +)] +public class AbpJsonSystemTextJsonTestModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddOptions() + .Configure((options, rootServiceProvider) => + { + if (options.JsonSerializerOptions.TypeInfoResolver != null) + { + var modifiers = options.JsonSerializerOptions.TypeInfoResolver.As().Modifiers; + modifiers.RemoveAll(x => x.Target?.GetType() == typeof(AbpDateTimeConverterModifier)); + modifiers.Add(new AbpDateTimeConverterModifier( + rootServiceProvider.GetRequiredService(), + rootServiceProvider.GetRequiredService()).CreateModifyAction()); + } + }); + } +} + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpJsonNewtonsoftModule), + typeof(AbpTestBaseModule) +)] +public class AbpJsonNewtonsoftTestModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddOptions() + .Configure((options, rootServiceProvider) => + { + options.JsonSerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver( + rootServiceProvider.GetRequiredService()); + }); + } +}