diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/post.md b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/post.md index e34a64337e..05a44625c9 100644 --- a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/post.md +++ b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/post.md @@ -8,7 +8,7 @@ In this article, we'll show you step by step how to handle multi-timezone in the ## Timezone Settings -The ABP framework provides a setting called `Abp.Timing.TimeZone` for setting and getting the timezone of users, tenants, or applications. The default value is `UTC`. Check out the [Timing documentation](https://abp.io/docs/latest/framework/infrastructure/timing) for more information. +The ABP framework provides a setting called `Abp.Timing.TimeZone` for setting and getting the timezone of users, tenants, or applications. The default value is empty, which means the application will use the server's time zone. Check out the [Timing documentation](https://abp.io/docs/latest/framework/infrastructure/timing) for more information. ## ISO 8601 Date Time Format diff --git a/docs/en/framework/infrastructure/timing.md b/docs/en/framework/infrastructure/timing.md index 262bb5c601..edcc69633c 100644 --- a/docs/en/framework/infrastructure/timing.md +++ b/docs/en/framework/infrastructure/timing.md @@ -157,7 +157,7 @@ This section covers the ABP infrastructure related to managing time zones. ### TimeZone Setting -ABP defines **a setting**, named `Abp.Timing.TimeZone`, that can be used to set and get the time zone for a user, [tenant](../architecture/multi-tenancy) or globally for the application. The default value is `UTC`. +ABP defines **a setting**, named `Abp.Timing.TimeZone`, that can be used to set and get the time zone for a user, [tenant](../architecture/multi-tenancy) or globally for the application. The default value is empty, which means the application will use the server's time zone. You can change your host/tenant global time zone in the [Settings Management UI](../../modules/setting-management#setting-management-ui) diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Timing/AbpTimeZoneMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Timing/AbpTimeZoneMiddleware.cs index 4bcfdf347b..df70441a31 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Timing/AbpTimeZoneMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Timing/AbpTimeZoneMiddleware.cs @@ -34,10 +34,9 @@ public class AbpTimeZoneMiddleware : AbpMiddlewareBase, ITransientDependency timezone = await settingProvider.GetOrNullAsync(TimingSettingNames.TimeZone); } - if (timezone.IsNullOrEmpty()) + if (timezone.IsNullOrWhiteSpace()) { - await next(context); - return; + timezone = context.RequestServices.GetRequiredService().GetCurrentIanaTimezoneName(); } var currentTimezoneProvider = context.RequestServices.GetRequiredService(); diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs index 01c1e2a720..d09f97b24c 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs @@ -20,6 +20,7 @@ using Volo.Abp.Json; using Volo.Abp.MultiTenancy; using Volo.Abp.Reflection; using Volo.Abp.Threading; +using Volo.Abp.Timing; using Volo.Abp.Tracing; namespace Volo.Abp.Http.Client.ClientProxying; @@ -33,6 +34,7 @@ public class ClientProxyBase : ITransientDependency protected ICorrelationIdProvider CorrelationIdProvider => LazyServiceProvider.LazyGetRequiredService(); protected ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService(); protected IOptions AbpCorrelationIdOptions => LazyServiceProvider.LazyGetRequiredService>(); + protected ICurrentTimezoneProvider CurrentTimezoneProvider => LazyServiceProvider.LazyGetRequiredService(); protected IProxyHttpClientFactory HttpClientFactory => LazyServiceProvider.LazyGetRequiredService(); protected IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider => LazyServiceProvider.LazyGetRequiredService(); protected IOptions ClientOptions => LazyServiceProvider.LazyGetRequiredService>(); @@ -337,6 +339,12 @@ public class ClientProxyBase : ITransientDependency //X-Requested-With requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest"); + + //Timezone + if (!CurrentTimezoneProvider.TimeZone.IsNullOrWhiteSpace()) + { + requestMessage.Headers.Add(TimeZoneConsts.DefaultTimeZoneKey, CurrentTimezoneProvider.TimeZone); + } } protected virtual StringSegment RemoveQuotes(StringSegment input) diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/ITimezoneProvider.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/ITimezoneProvider.cs index 89b59724a4..8c649619e5 100644 --- a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/ITimezoneProvider.cs +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/ITimezoneProvider.cs @@ -14,4 +14,8 @@ public interface ITimezoneProvider string IanaToWindows(string ianaTimeZoneName); TimeZoneInfo GetTimeZoneInfo(string windowsOrIanaTimeZoneId); + + string GetCurrentWindowsTimezoneName(); + + string GetCurrentIanaTimezoneName(); } diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs index 565c04c6fa..a009f64e9e 100644 --- a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs @@ -32,4 +32,15 @@ public class TZConvertTimezoneProvider : ITimezoneProvider, ITransientDependency { return TZConvert.GetTimeZoneInfo(windowsOrIanaTimeZoneId); } + + public virtual string GetCurrentWindowsTimezoneName() + { + return TimeZoneInfo.Local.StandardName;; + } + + public virtual string GetCurrentIanaTimezoneName() + { + var timezone = GetCurrentWindowsTimezoneName(); + return TZConvert.WindowsToIana(timezone); + } } diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs index 066747df94..343e20feb5 100644 --- a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs @@ -10,7 +10,7 @@ public class TimingSettingProvider : SettingDefinitionProvider { context.Add( new SettingDefinition(TimingSettingNames.TimeZone, - "UTC", + "", L("DisplayName:Abp.Timing.Timezone"), L("Description:Abp.Timing.Timezone"), isVisibleToClients: true) diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/AbpTimeZoneMiddleware_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/AbpTimeZoneMiddleware_Tests.cs index f3da8fb77c..7168c6c4a7 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/AbpTimeZoneMiddleware_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/AbpTimeZoneMiddleware_Tests.cs @@ -18,11 +18,13 @@ namespace Volo.Abp.AspNetCore.Mvc.Timing; public class AbpTimeZoneMiddleware_Tests : AspNetCoreMvcTestBase { private readonly ICurrentTimezoneProvider _currentTimezoneProvider; + private readonly ITimezoneProvider _timezoneProvider; private readonly FakeUserClaims _fakeRequiredService; public AbpTimeZoneMiddleware_Tests() { _currentTimezoneProvider = GetRequiredService(); + _timezoneProvider = GetRequiredService(); _fakeRequiredService = GetRequiredService(); } @@ -40,7 +42,7 @@ public class AbpTimeZoneMiddleware_Tests : AspNetCoreMvcTestBase using (_currentTimezoneProvider.Change("UTC")) { var result = await Client.GetStringAsync("api/timing-test"); - result.ShouldBe("UTC"); + result.ShouldBe(_timezoneProvider.GetCurrentIanaTimezoneName()); } // Query string @@ -87,14 +89,15 @@ public class AbpTimeZoneMiddleware_Tests : AspNetCoreMvcTestBase using (_currentTimezoneProvider.Change("Europe/Berlin")) { var result = await Client.GetStringAsync("api/timing-test"); - result.ShouldBe("UTC"); + + result.ShouldBe(_timezoneProvider.GetCurrentIanaTimezoneName()); } // Query string using (_currentTimezoneProvider.Change("Europe/Berlin")) { var result = await Client.GetStringAsync("api/timing-test?__timezone=Europe/Istanbul"); - result.ShouldBe("UTC"); + result.ShouldBe(_timezoneProvider.GetCurrentIanaTimezoneName()); } // Header