From 7aa72892312b90c44082700552f569fe9c7964b1 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Thu, 31 Aug 2023 17:47:53 +0200 Subject: [PATCH 01/14] Initial changed for timezone hybrid mode --- .../src/Interop/Interop.TimeZoneInfo.iOS.cs | 21 +++++ .../System.Private.CoreLib.Shared.projitems | 14 ++-- ...TimeZoneInfo.FullGlobalizationData.Unix.cs | 50 +++++++++--- .../TimeZoneInfo.FullGlobalizationData.cs | 10 +++ .../TimeZoneInfo.MinimalGlobalizationData.cs | 47 ----------- .../src/System/TimeZoneInfo.Unix.cs | 17 +++- .../System.Runtime/System.Runtime.sln | 2 + .../Hybrid/System.Runtime.IOS.Tests.csproj | 22 +++++ .../tests/System/TimeZoneInfoTests.cs | 9 ++- src/mono/mono/mini/CMakeLists.txt | 3 +- .../CMakeLists.txt | 3 +- .../System.Globalization.Native/entrypoints.c | 1 + .../pal_timeZoneInfo.h | 5 ++ .../pal_timeZoneInfo.m | 80 +++++++++++++++++++ 14 files changed, 212 insertions(+), 72 deletions(-) create mode 100644 src/libraries/Common/src/Interop/Interop.TimeZoneInfo.iOS.cs delete mode 100644 src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs create mode 100644 src/libraries/System.Runtime/tests/Hybrid/System.Runtime.IOS.Tests.csproj create mode 100644 src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m diff --git a/src/libraries/Common/src/Interop/Interop.TimeZoneInfo.iOS.cs b/src/libraries/Common/src/Interop/Interop.TimeZoneInfo.iOS.cs new file mode 100644 index 00000000000000..9575fc3dc3359c --- /dev/null +++ b/src/libraries/Common/src/Interop/Interop.TimeZoneInfo.iOS.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Globalization + { + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetTimeZoneDisplayNameNative", StringMarshalling = StringMarshalling.Utf16)] + internal static unsafe partial ResultCode GetTimeZoneDisplayNameNative( + string localeName, + int lNameLength, + string timeZoneId, + int idLength, + TimeZoneDisplayNameType type, + char* result, + int resultLength); + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 14b8a814732670..2697c28b020f30 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -1272,7 +1272,7 @@ - + @@ -1357,12 +1357,15 @@ Common\Interop\Interop.ResultCode.cs - + Common\Interop\Interop.TimeZoneDisplayNameType.cs - + Common\Interop\Interop.TimeZoneInfo.cs + + Common\Interop\Interop.TimeZoneInfo.iOS.cs + Common\Interop\Interop.Utils.cs @@ -2500,7 +2503,7 @@ - + @@ -2516,9 +2519,6 @@ - - - Common\Interop\OSX\Interop.libobjc.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index c10fdfb54be855..d76458f8373220 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -28,6 +28,14 @@ public sealed partial class TimeZoneInfo // Helper function to get the standard display name for the UTC static time zone instance private static string GetUtcStandardDisplayName() { + System.Diagnostics.Debug.Write("TimeZoneInfo.GetUtcStandardDisplayName is called.\n"); +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (!GlobalizationMode.Hybrid) + { + // For this target, be consistent with other time zone display names that use an abbreviation. + return "UTC"; + } +#endif // Don't bother looking up the name for invariant or English cultures CultureInfo uiCulture = CultureInfo.CurrentUICulture; if (GlobalizationMode.Invariant || uiCulture.Name.Length == 0 || uiCulture.TwoLetterISOLanguageName == "en") @@ -48,6 +56,13 @@ private static string GetUtcStandardDisplayName() // Helper function to get the full display name for the UTC static time zone instance private static string GetUtcFullDisplayName(string timeZoneId, string standardDisplayName) { +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (!GlobalizationMode.Hybrid) + { + // For this target, be consistent with other time zone display names that use the ID. + return $"(UTC) {timeZoneId}"; + } +#endif return $"(UTC) {standardDisplayName}"; } #pragma warning restore IDE0060 @@ -89,19 +104,24 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati return; } - string? timeZoneDisplayName; - bool result = Interop.CallStringMethod( - (buffer, locale, id, type) => + string? timeZoneDisplayName; + bool result = Interop.CallStringMethod( + (buffer, locale, id, type) => + { + fixed (char* bufferPtr = buffer) { - fixed (char* bufferPtr = buffer) - { - return Interop.Globalization.GetTimeZoneDisplayName(locale, id, type, bufferPtr, buffer.Length); - } +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + return Interop.Globalization.GetTimeZoneDisplayNameNative(locale, locale.Length, id, id.Length, type, bufferPtr, buffer.Length); +#endif + return Interop.Globalization.GetTimeZoneDisplayName(locale, id, type, bufferPtr, buffer.Length); + } }, uiCulture, timeZoneId, nameType, out timeZoneDisplayName); +System.Diagnostics.Debug.Write("After First call TimeZoneInfo.GetDisplayName: timeZoneDisplayName = " + timeZoneDisplayName + "\n"); if (!result && uiCulture != FallbackCultureName) { @@ -111,6 +131,10 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati { fixed (char* bufferPtr = buffer) { +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + return Interop.Globalization.GetTimeZoneDisplayNameNative(locale, locale.Length, id, id.Length, type, bufferPtr, buffer.Length); +#endif return Interop.Globalization.GetTimeZoneDisplayName(locale, id, type, bufferPtr, buffer.Length); } }, @@ -119,7 +143,6 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati nameType, out timeZoneDisplayName); } - // If there is an unknown error, don't set the displayName field. // It will be set to the abbreviation that was read out of the tzfile. if (result && !string.IsNullOrEmpty(timeZoneDisplayName)) @@ -239,7 +262,7 @@ private static void GetFullValueForDisplayNameField(string timeZoneId, TimeSpan // Helper function that gets an exmplar city name either from ICU or from the IANA time zone ID itself private static string GetExemplarCityName(string timeZoneId, string uiCultureName) - { + {// // First try to get the name through the localization data. string? exemplarCityName = null; GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.ExemplarCity, uiCultureName, ref exemplarCityName); @@ -256,8 +279,17 @@ private static string GetExemplarCityName(string timeZoneId, string uiCultureNam // Helper function that returns an alternative ID using ICU data. Used primarily for converting from Windows IDs. private static unsafe string? GetAlternativeId(string id, out bool idIsIana) { +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + //if (!GlobalizationMode.Hybrid) + //{ + // No alternative IDs in this target. + idIsIana = false; + return null; + //} +#else idIsIana = false; return TryConvertWindowsIdToIanaId(id, null, out string? ianaId) ? ianaId : null; +#endif } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs index 17b677ca37a9ae..09b05f15a8cd87 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs @@ -9,6 +9,10 @@ public sealed partial class TimeZoneInfo { private static unsafe bool TryConvertIanaIdToWindowsId(string ianaId, bool allocate, out string? windowsId) { +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER + windowsId = null; + return false; +#else if (GlobalizationMode.Invariant || GlobalizationMode.UseNls || ianaId is null || @@ -28,10 +32,15 @@ ianaId is null || windowsId = null; return false; +#endif } private static unsafe bool TryConvertWindowsIdToIanaId(string windowsId, string? region, bool allocate, out string? ianaId) { +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER + ianaId = null; + return false; +#else // This functionality is not enabled in the browser for the sake of size reduction. if (GlobalizationMode.Invariant || GlobalizationMode.UseNls || windowsId is null) { @@ -88,6 +97,7 @@ private static unsafe bool TryConvertWindowsIdToIanaId(string windowsId, string? ianaId = null; return false; +#endif } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs deleted file mode 100644 index fa1d25e4933352..00000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System -{ - public sealed partial class TimeZoneInfo - { -#pragma warning disable IDE0060 - static partial void GetFullValueForDisplayNameField(string timeZoneId, TimeSpan baseUtcOffset, ref string? displayName); - - static partial void GetStandardDisplayName(string timeZoneId, ref string? displayName); - - static partial void GetDaylightDisplayName(string timeZoneId, ref string? displayName); - - private static string GetUtcStandardDisplayName() - { - // For this target, be consistent with other time zone display names that use an abbreviation. - return "UTC"; - } - - private static string GetUtcFullDisplayName(string timeZoneId, string standardDisplayName) - { - // For this target, be consistent with other time zone display names that use the ID. - return $"(UTC) {timeZoneId}"; - } - - private static string? GetAlternativeId(string id, out bool idIsIana) - { - // No alternative IDs in this target. - idIsIana = false; - return null; - } - - private static unsafe bool TryConvertIanaIdToWindowsId(string ianaId, bool allocate, out string? windowsId) - { - windowsId = null; - return false; - } - - private static unsafe bool TryConvertWindowsIdToIanaId(string windowsId, string? region, bool allocate, out string? ianaId) - { - ianaId = null; - return false; - } -#pragma warning restore IDE0060 - } -} diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index 2524b4fd536066..a6157e256c6667 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -231,9 +231,14 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return displayName; +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER + return displayName; + // if (GlobalizationMode.Hybrid) + // GetFullValueForDisplayNameField(Id, BaseUtcOffset, ref displayName); +#else GetFullValueForDisplayNameField(Id, BaseUtcOffset, ref displayName); - return displayName; +#endif } private string? PopulateStandardDisplayName() @@ -245,8 +250,11 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return standardDisplayName; +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER + if (!GlobalizationMode.Hybrid) + return standardDisplayName; +#endif GetStandardDisplayName(Id, ref standardDisplayName); - return standardDisplayName; } @@ -259,8 +267,11 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return daylightDisplayName; +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (!GlobalizationMode.Hybrid) + return daylightDisplayName; +#endif GetDaylightDisplayName(Id, ref daylightDisplayName); - return daylightDisplayName; } diff --git a/src/libraries/System.Runtime/System.Runtime.sln b/src/libraries/System.Runtime/System.Runtime.sln index a7d50d4a347abd..4ef7e0094581f3 100644 --- a/src/libraries/System.Runtime/System.Runtime.sln +++ b/src/libraries/System.Runtime/System.Runtime.sln @@ -27,6 +27,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.Nls.Tests", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.Tests", "tests\System.Runtime.Tests.csproj", "{4EE36055-AD7C-4779-B3F6-08687960DCC3}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.IOS.Tests", "tests\Hybrid\System.Runtime.IOS.Tests.csproj", "{4EE36055-AD7C-4779-B3F6-08687960DCC3}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.ReflectionInvokeEmit.Tests", "tests\System\Reflection\InvokeEmit\System.Runtime.ReflectionInvokeEmit.Tests.csproj", "{C3F25EEF-04B4-407A-960B-0C1CE9C04430}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.ReflectionInvokeInterpreted.Tests", "tests\System\Reflection\InvokeInterpreted\System.Runtime.ReflectionInvokeInterpreted.Tests.csproj", "{47E26787-7C27-4572-AD8B-868DE44E2C48}" diff --git a/src/libraries/System.Runtime/tests/Hybrid/System.Runtime.IOS.Tests.csproj b/src/libraries/System.Runtime/tests/Hybrid/System.Runtime.IOS.Tests.csproj new file mode 100644 index 00000000000000..7ab499979f3928 --- /dev/null +++ b/src/libraries/System.Runtime/tests/Hybrid/System.Runtime.IOS.Tests.csproj @@ -0,0 +1,22 @@ + + + $(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-maccatalyst + true + true + true + true + + + + + $(WithoutCategories);AdditionalTimezoneChecks + + + + + + + + diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 7efe9c0cde1dcf..d0e98f58afee03 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -89,7 +89,7 @@ public static void Names() // Name abbreviations, if available, are used instead public static IEnumerable Platform_TimeZoneNamesTestData() { - if (PlatformDetection.IsBrowser || PlatformDetection.IsiOS || PlatformDetection.IstvOS) + if (PlatformDetection.IsBrowser || (!PlatformDetection.IsHybridGlobalizationOnOSX && (PlatformDetection.IsiOS || PlatformDetection.IstvOS))) return new TheoryData { { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) America/Los_Angeles", null, "PST", "PDT" }, @@ -137,9 +137,10 @@ public static void Platform_TimeZoneNames(TimeZoneInfo tzi, string displayName, displayName = displayName.Replace(c.ToString(), "", StringComparison.Ordinal); } } + System.Diagnostics.Debug.Write("Platform_TimeZoneNames: Display Name: " + tzi.DisplayName + "\n"+ alternativeDisplayName + "\n" + displayName + "\n" + standardName + "\n" + daylightName + "\n"); - Assert.True(displayName == tzi.DisplayName || alternativeDisplayName == tzi.DisplayName, - $"Display Name: Neither '{displayName}' nor '{alternativeDisplayName}' equal to '{tzi.DisplayName}'"); + // Assert.True(displayName == tzi.DisplayName || alternativeDisplayName == tzi.DisplayName, + // $"Display Name: Neither '{displayName}' nor '{alternativeDisplayName}' equal to '{tzi.DisplayName}'"); Assert.Equal(standardName, tzi.StandardName); Assert.Equal(daylightName, tzi.DaylightName); } @@ -2802,7 +2803,7 @@ public static void TimeZoneInfo_DisplayNameStartsWithOffset(TimeZoneInfo tzi) if (PlatformDetection.IsNotWindowsNanoServer && !PlatformDetection.IsWindows7) { string offset = (match.Groups["sign"].Value == "-" ? "-" : "") + match.Groups["amount"].Value; - TimeSpan ts = TimeSpan.Parse(offset); + TimeSpan ts = TimeSpan.Parse(offset);// this throws exception if (PlatformDetection.IsWindows && tzi.BaseUtcOffset != ts && (tzi.Id.Contains("Morocco") || tzi.Id.Contains("Volgograd"))) diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index 6b300ab2b74cfa..01a0cd68e8d3ef 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -75,7 +75,8 @@ if(HAVE_SYS_ICU) pal_collation.m pal_casing.m pal_calendarData.m - pal_normalization.m) + pal_normalization.m + pal_timeZoneInfo.m) addprefix(icu_shim_darwin_sources "${ICU_SHIM_PATH}" "${icu_shim_darwin_sources_base}") set(icu_shim_sources ${icu_shim_sources} ${icu_shim_darwin_sources}) diff --git a/src/native/libs/System.Globalization.Native/CMakeLists.txt b/src/native/libs/System.Globalization.Native/CMakeLists.txt index d6dfcb65bf3284..d218c968eb04b4 100644 --- a/src/native/libs/System.Globalization.Native/CMakeLists.txt +++ b/src/native/libs/System.Globalization.Native/CMakeLists.txt @@ -98,7 +98,8 @@ if (CLR_CMAKE_TARGET_APPLE) pal_collation.m pal_casing.m pal_calendarData.m - pal_normalization.m) + pal_normalization.m + pal_timeZoneInfo.m) set_source_files_properties(${NATIVEGLOBALIZATION_SOURCES_OBJC} PROPERTIES COMPILE_FLAGS "-fobjc-arc ${CLR_CMAKE_COMMON_OBJC_FLAGS}") set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} ${NATIVEGLOBALIZATION_SOURCES_OBJC}) endif() diff --git a/src/native/libs/System.Globalization.Native/entrypoints.c b/src/native/libs/System.Globalization.Native/entrypoints.c index 11ab93883cb0d9..799b15ed2ca760 100644 --- a/src/native/libs/System.Globalization.Native/entrypoints.c +++ b/src/native/libs/System.Globalization.Native/entrypoints.c @@ -70,6 +70,7 @@ static const Entry s_globalizationNative[] = DllImportEntry(GlobalizationNative_GetLocaleInfoStringNative) DllImportEntry(GlobalizationNative_GetLocaleNameNative) DllImportEntry(GlobalizationNative_GetLocaleTimeFormatNative) + DllImportEntry(GlobalizationNative_GetTimeZoneDisplayNameNative) DllImportEntry(GlobalizationNative_IndexOfNative) DllImportEntry(GlobalizationNative_IsNormalizedNative) DllImportEntry(GlobalizationNative_NormalizeStringNative) diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h index b91469e6a1341a..9e57b12dc2cbe7 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h @@ -23,3 +23,8 @@ typedef enum PALEXPORT int32_t GlobalizationNative_WindowsIdToIanaId(const UChar* windowsId, const char* region, UChar* ianaId, int32_t ianaIdLength); PALEXPORT int32_t GlobalizationNative_IanaIdToWindowsId(const UChar* ianaId, UChar* windowsId, int32_t windowsIdLength); PALEXPORT ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* localeName, const UChar* timeZoneId, TimeZoneDisplayNameType type, UChar* result, int32_t resultLength); + +#ifdef __APPLE__ +PALEXPORT int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* timeZoneId, int32_t timeZoneIdLength, + TimeZoneDisplayNameType type, uint16_t* result, int32_t resultLength); +#endif \ No newline at end of file diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m new file mode 100644 index 00000000000000..71db157f98803c --- /dev/null +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +#include +#include +#include + +#include "pal_errors_internal.h" +#include "pal_locale_internal.h" +#include "pal_timeZoneInfo.h" + +#import +#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) + +/* +Gets the localized display name that is currently in effect for the specified time zone. +*/ +int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* timeZoneId, int32_t timeZoneIdLength, + TimeZoneDisplayNameType type, uint16_t* result, int32_t resultLength) +{ + @autoreleasepool + { + NSLocale *currentLocale; + if(localeName == NULL || lNameLength == 0) + { + currentLocale = [NSLocale systemLocale]; + } + else + { + NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength]; + currentLocale = [NSLocale localeWithLocaleIdentifier:locName]; + } + //NSTimeZone* timeZone = [NSTimeZone localTimeZone]; + NSString* tzName = [NSString stringWithCharacters: timeZoneId length: timeZoneIdLength]; + NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:tzName]; + NSTimeZoneNameStyle style; + + switch (type) + { + case TimeZoneDisplayName_Standard: + style = NSTimeZoneNameStyleStandard;//;NSTimeZoneNameStyleShortStandard + break; + case TimeZoneDisplayName_DaylightSavings: + style = NSTimeZoneNameStyleDaylightSaving;//;NSTimeZoneNameStyleShortDaylightSaving + break; + case TimeZoneDisplayName_Generic: + style = NSTimeZoneNameStyleGeneric;//;NSTimeZoneNameStyleShortGeneric + break; + // case TimeZoneDisplayName_GenericLocation: + // style = NSTimeZoneNameStyleStandard;//??? + // break; + // case TimeZoneDisplayName_ExemplarCity: + // style = NSTimeZoneNameStyleStandard;//?? + // break; + default: + return UnknownError;//-1; + } + + NSString* timeZoneName = [timeZone localizedName:style locale:currentLocale]; + if (timeZoneName == NULL || timeZoneName.length == 0) + { + return UnknownError;//0 + } + + int32_t index = 0, dstIdx = 0, isError = 0; + uint16_t dstCodepoint; + while (index < timeZoneName.length) + { + dstCodepoint = [timeZoneName characterAtIndex: index]; + Append(result, dstIdx, resultLength, dstCodepoint, isError); + index++; + } + dstCodepoint = '\0'; + Append(result, dstIdx, resultLength, dstCodepoint, isError); + + return isError ? UnknownError : Success;//timeZoneName.length;//; + } +} +#endif From cfd0f5ba6e910676cef53b0f867029fabf9add7d Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 1 Sep 2023 12:03:21 +0200 Subject: [PATCH 02/14] Refactoring --- ...TimeZoneInfo.FullGlobalizationData.Unix.cs | 57 ++++++++++--------- .../TimeZoneInfo.FullGlobalizationData.cs | 8 +-- .../src/System/TimeZoneInfo.Unix.cs | 9 ++- .../Hybrid/System.Runtime.IOS.Tests.csproj | 3 - .../tests/System/TimeZoneInfoTests.cs | 7 +-- .../pal_timeZoneInfo.h | 4 +- .../pal_timeZoneInfo.m | 1 - 7 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index d76458f8373220..72d1e8195ac27d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -29,7 +29,10 @@ public sealed partial class TimeZoneInfo private static string GetUtcStandardDisplayName() { System.Diagnostics.Debug.Write("TimeZoneInfo.GetUtcStandardDisplayName is called.\n"); -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS +#if TARGET_BROWSER || TARGET_WASI + // For this target, be consistent with other time zone display names that use an abbreviation. + return "UTC"; +#elif TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) { // For this target, be consistent with other time zone display names that use an abbreviation. @@ -56,7 +59,10 @@ private static string GetUtcStandardDisplayName() // Helper function to get the full display name for the UTC static time zone instance private static string GetUtcFullDisplayName(string timeZoneId, string standardDisplayName) { -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS +#if TARGET_BROWSER || TARGET_WASI + // For this target, be consistent with other time zone display names that use the ID. + return $"(UTC) {timeZoneId}"; +#elif TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) { // For this target, be consistent with other time zone display names that use the ID. @@ -104,24 +110,23 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati return; } - string? timeZoneDisplayName; - bool result = Interop.CallStringMethod( - (buffer, locale, id, type) => - { - fixed (char* bufferPtr = buffer) + string? timeZoneDisplayName; + bool result = Interop.CallStringMethod( + (buffer, locale, id, type) => { -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS - if (GlobalizationMode.Hybrid) - return Interop.Globalization.GetTimeZoneDisplayNameNative(locale, locale.Length, id, id.Length, type, bufferPtr, buffer.Length); + fixed (char* bufferPtr = buffer) + { +#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI + if (GlobalizationMode.Hybrid) + return Interop.Globalization.GetTimeZoneDisplayNameNative(locale, locale.Length, id, id.Length, type, bufferPtr, buffer.Length); #endif - return Interop.Globalization.GetTimeZoneDisplayName(locale, id, type, bufferPtr, buffer.Length); - } - }, - uiCulture, - timeZoneId, - nameType, - out timeZoneDisplayName); -System.Diagnostics.Debug.Write("After First call TimeZoneInfo.GetDisplayName: timeZoneDisplayName = " + timeZoneDisplayName + "\n"); + return Interop.Globalization.GetTimeZoneDisplayName(locale, id, type, bufferPtr, buffer.Length); + } + }, + uiCulture, + timeZoneId, + nameType, + out timeZoneDisplayName); if (!result && uiCulture != FallbackCultureName) { @@ -131,7 +136,7 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati { fixed (char* bufferPtr = buffer) { -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS +#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI if (GlobalizationMode.Hybrid) return Interop.Globalization.GetTimeZoneDisplayNameNative(locale, locale.Length, id, id.Length, type, bufferPtr, buffer.Length); #endif @@ -143,6 +148,7 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati nameType, out timeZoneDisplayName); } + // If there is an unknown error, don't set the displayName field. // It will be set to the abbreviation that was read out of the tzfile. if (result && !string.IsNullOrEmpty(timeZoneDisplayName)) @@ -262,7 +268,7 @@ private static void GetFullValueForDisplayNameField(string timeZoneId, TimeSpan // Helper function that gets an exmplar city name either from ICU or from the IANA time zone ID itself private static string GetExemplarCityName(string timeZoneId, string uiCultureName) - {// + { // First try to get the name through the localization data. string? exemplarCityName = null; GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.ExemplarCity, uiCultureName, ref exemplarCityName); @@ -279,13 +285,10 @@ private static string GetExemplarCityName(string timeZoneId, string uiCultureNam // Helper function that returns an alternative ID using ICU data. Used primarily for converting from Windows IDs. private static unsafe string? GetAlternativeId(string id, out bool idIsIana) { -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS - //if (!GlobalizationMode.Hybrid) - //{ - // No alternative IDs in this target. - idIsIana = false; - return null; - //} +#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI + // No alternative IDs in this target. + idIsIana = false; + return null; #else idIsIana = false; return TryConvertWindowsIdToIanaId(id, null, out string? ianaId) ? ianaId : null; diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs index 09b05f15a8cd87..6c2e3a962526ec 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs @@ -9,7 +9,7 @@ public sealed partial class TimeZoneInfo { private static unsafe bool TryConvertIanaIdToWindowsId(string ianaId, bool allocate, out string? windowsId) { -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER +#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI windowsId = null; return false; #else @@ -37,9 +37,9 @@ ianaId is null || private static unsafe bool TryConvertWindowsIdToIanaId(string windowsId, string? region, bool allocate, out string? ianaId) { -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER - ianaId = null; - return false; +#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI + ianaId = null; + return false; #else // This functionality is not enabled in the browser for the sake of size reduction. if (GlobalizationMode.Invariant || GlobalizationMode.UseNls || windowsId is null) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index a6157e256c6667..e5a36bee754e9b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -231,10 +231,8 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return displayName; -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER +#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI return displayName; - // if (GlobalizationMode.Hybrid) - // GetFullValueForDisplayNameField(Id, BaseUtcOffset, ref displayName); #else GetFullValueForDisplayNameField(Id, BaseUtcOffset, ref displayName); return displayName; @@ -250,11 +248,12 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return standardDisplayName; -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER +#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI if (!GlobalizationMode.Hybrid) return standardDisplayName; #endif GetStandardDisplayName(Id, ref standardDisplayName); + return standardDisplayName; } @@ -267,7 +266,7 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return daylightDisplayName; -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS +#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI if (!GlobalizationMode.Hybrid) return daylightDisplayName; #endif diff --git a/src/libraries/System.Runtime/tests/Hybrid/System.Runtime.IOS.Tests.csproj b/src/libraries/System.Runtime/tests/Hybrid/System.Runtime.IOS.Tests.csproj index 7ab499979f3928..ca2e3b7856cda5 100644 --- a/src/libraries/System.Runtime/tests/Hybrid/System.Runtime.IOS.Tests.csproj +++ b/src/libraries/System.Runtime/tests/Hybrid/System.Runtime.IOS.Tests.csproj @@ -7,9 +7,6 @@ true - $(WithoutCategories);AdditionalTimezoneChecks diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index d0e98f58afee03..f0caaed62a69a7 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -137,10 +137,9 @@ public static void Platform_TimeZoneNames(TimeZoneInfo tzi, string displayName, displayName = displayName.Replace(c.ToString(), "", StringComparison.Ordinal); } } - System.Diagnostics.Debug.Write("Platform_TimeZoneNames: Display Name: " + tzi.DisplayName + "\n"+ alternativeDisplayName + "\n" + displayName + "\n" + standardName + "\n" + daylightName + "\n"); - // Assert.True(displayName == tzi.DisplayName || alternativeDisplayName == tzi.DisplayName, - // $"Display Name: Neither '{displayName}' nor '{alternativeDisplayName}' equal to '{tzi.DisplayName}'"); + Assert.True(displayName == tzi.DisplayName || alternativeDisplayName == tzi.DisplayName, + $"Display Name: Neither '{displayName}' nor '{alternativeDisplayName}' equal to '{tzi.DisplayName}'"); Assert.Equal(standardName, tzi.StandardName); Assert.Equal(daylightName, tzi.DaylightName); } @@ -2803,7 +2802,7 @@ public static void TimeZoneInfo_DisplayNameStartsWithOffset(TimeZoneInfo tzi) if (PlatformDetection.IsNotWindowsNanoServer && !PlatformDetection.IsWindows7) { string offset = (match.Groups["sign"].Value == "-" ? "-" : "") + match.Groups["amount"].Value; - TimeSpan ts = TimeSpan.Parse(offset);// this throws exception + TimeSpan ts = TimeSpan.Parse(offset); if (PlatformDetection.IsWindows && tzi.BaseUtcOffset != ts && (tzi.Id.Contains("Morocco") || tzi.Id.Contains("Volgograd"))) diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h index 9e57b12dc2cbe7..28a00e89186a77 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h @@ -26,5 +26,5 @@ PALEXPORT ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* loc #ifdef __APPLE__ PALEXPORT int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* timeZoneId, int32_t timeZoneIdLength, - TimeZoneDisplayNameType type, uint16_t* result, int32_t resultLength); -#endif \ No newline at end of file + TimeZoneDisplayNameType type, uint16_t* result, int32_t resultLength); +#endif diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m index 71db157f98803c..b9776af63fb636 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m @@ -31,7 +31,6 @@ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeN NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength]; currentLocale = [NSLocale localeWithLocaleIdentifier:locName]; } - //NSTimeZone* timeZone = [NSTimeZone localTimeZone]; NSString* tzName = [NSString stringWithCharacters: timeZoneId length: timeZoneIdLength]; NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:tzName]; NSTimeZoneNameStyle style; From 3678a4869a4e74d0757b9cd26ee62ea458b3f73e Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 1 Sep 2023 13:27:10 +0200 Subject: [PATCH 03/14] Fix test failure on ios --- .../System.Runtime/tests/System/TimeZoneInfoTests.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index f0caaed62a69a7..c44010cf2618ca 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -100,6 +100,16 @@ public static IEnumerable Platform_TimeZoneNamesTestData() { s_NewfoundlandTz, "(UTC-03:30) America/St_Johns", null, "NST", "NDT" }, { s_catamarcaTz, "(UTC-03:00) America/Argentina/Catamarca", null, "-03", "-02" } }; + else if(PlatformDetection.IsHybridGlobalizationOnOSX && (PlatformDetection.IsiOS || PlatformDetection.IstvOS)) + return new TheoryData + { + { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) America/Los_Angeles", null, "Pacific Standard Time", "Pacific Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strSydney), "(UTC+10:00) Australia/Sydney", null, "Australian Eastern Standard Time", "Australian Eastern Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strPerth), "(UTC+08:00) Australia/Perth", null, "Australian Western Standard Time", "Australian Western Daylight Time" }, + { TimeZoneInfo.FindSystemTimeZoneById(s_strIran), "(UTC+03:30) Asia/Tehran", "(UTC+03:30) Iran Standard Time (Tehran)", "Iran Standard Time", "Iran Daylight Time" }, + { s_NewfoundlandTz, "(UTC-03:30) America/St_Johns", null, "Newfoundland Standard Time", "Newfoundland Daylight Time" }, + { s_catamarcaTz, "(UTC-03:00) America/Argentina/Catamarca", null, "Argentina Standard Time", "Argentina Summer Time" } + }; else if (PlatformDetection.IsWindows) return new TheoryData { From 8cf560993ee6f63a3e85974cbf27587fa5e12568 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 1 Sep 2023 14:24:09 +0200 Subject: [PATCH 04/14] Fix wasm build failure --- .../src/System.Private.CoreLib.Shared.projitems | 2 +- .../System/TimeZoneInfo.FullGlobalizationData.Unix.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 2697c28b020f30..69f337b32600fb 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -2476,6 +2476,7 @@ + @@ -2503,7 +2504,6 @@ - diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index 72d1e8195ac27d..2660dd8b01ab9c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -122,11 +122,11 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati #endif return Interop.Globalization.GetTimeZoneDisplayName(locale, id, type, bufferPtr, buffer.Length); } - }, - uiCulture, - timeZoneId, - nameType, - out timeZoneDisplayName); + }, + uiCulture, + timeZoneId, + nameType, + out timeZoneDisplayName); if (!result && uiCulture != FallbackCultureName) { From b44508f68667803fc065e43d99da23b1ff278cce Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 1 Sep 2023 14:46:09 +0200 Subject: [PATCH 05/14] Fix wasm build --- .../System.Private.CoreLib.Shared.projitems | 14 ++++-- ...TimeZoneInfo.FullGlobalizationData.Unix.cs | 16 ++----- ...imeZoneInfo.MinimalGlobalizationData.cs.cs | 47 +++++++++++++++++++ .../src/System/TimeZoneInfo.Unix.cs | 6 +-- 4 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs.cs diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 69f337b32600fb..2b30fdc91f6bd8 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -20,7 +20,7 @@ $(MSBuildThisFileDirectory)ILLink\ true true - true + true $(DefineConstants);BIGENDIAN @@ -1272,7 +1272,7 @@ - + @@ -1357,10 +1357,10 @@ Common\Interop\Interop.ResultCode.cs - + Common\Interop\Interop.TimeZoneDisplayNameType.cs - + Common\Interop\Interop.TimeZoneInfo.cs @@ -2476,7 +2476,7 @@ - + @@ -2504,6 +2504,7 @@ + @@ -2519,6 +2520,9 @@ + + + Common\Interop\OSX\Interop.libobjc.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index 2660dd8b01ab9c..aba934dfed64a9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -29,10 +29,7 @@ public sealed partial class TimeZoneInfo private static string GetUtcStandardDisplayName() { System.Diagnostics.Debug.Write("TimeZoneInfo.GetUtcStandardDisplayName is called.\n"); -#if TARGET_BROWSER || TARGET_WASI - // For this target, be consistent with other time zone display names that use an abbreviation. - return "UTC"; -#elif TARGET_IOS || TARGET_TVOS +#if TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) { // For this target, be consistent with other time zone display names that use an abbreviation. @@ -59,10 +56,7 @@ private static string GetUtcStandardDisplayName() // Helper function to get the full display name for the UTC static time zone instance private static string GetUtcFullDisplayName(string timeZoneId, string standardDisplayName) { -#if TARGET_BROWSER || TARGET_WASI - // For this target, be consistent with other time zone display names that use the ID. - return $"(UTC) {timeZoneId}"; -#elif TARGET_IOS || TARGET_TVOS +#if TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) { // For this target, be consistent with other time zone display names that use the ID. @@ -116,7 +110,7 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati { fixed (char* bufferPtr = buffer) { -#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI +#if TARGET_IOS || TARGET_TVOS if (GlobalizationMode.Hybrid) return Interop.Globalization.GetTimeZoneDisplayNameNative(locale, locale.Length, id, id.Length, type, bufferPtr, buffer.Length); #endif @@ -136,7 +130,7 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati { fixed (char* bufferPtr = buffer) { -#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI +#if TARGET_IOS || TARGET_TVOS if (GlobalizationMode.Hybrid) return Interop.Globalization.GetTimeZoneDisplayNameNative(locale, locale.Length, id, id.Length, type, bufferPtr, buffer.Length); #endif @@ -285,7 +279,7 @@ private static string GetExemplarCityName(string timeZoneId, string uiCultureNam // Helper function that returns an alternative ID using ICU data. Used primarily for converting from Windows IDs. private static unsafe string? GetAlternativeId(string id, out bool idIsIana) { -#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI +#if TARGET_IOS || TARGET_TVOS // No alternative IDs in this target. idIsIana = false; return null; diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs.cs new file mode 100644 index 00000000000000..b04b616d4f5db8 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System +{ + public sealed partial class TimeZoneInfo + { +#pragma warning disable IDE0060 + static partial void GetFullValueForDisplayNameField(string timeZoneId, TimeSpan baseUtcOffset, ref string? displayName); + + static partial void GetStandardDisplayName(string timeZoneId, ref string? displayName); + + static partial void GetDaylightDisplayName(string timeZoneId, ref string? displayName); + + private static string GetUtcStandardDisplayName() + { + // For this target, be consistent with other time zone display names that use an abbreviation. + return "UTC"; + } + + private static string GetUtcFullDisplayName(string timeZoneId, string standardDisplayName) + { + // For this target, be consistent with other time zone display names that use the ID. + return $"(UTC) {timeZoneId}"; + } + + private static string? GetAlternativeId(string id, out bool idIsIana) + { + // No alternative IDs in this target. + idIsIana = false; + return null; + } + + private static unsafe bool TryConvertIanaIdToWindowsId(string ianaId, bool allocate, out string? windowsId) + { + windowsId = null; + return false; + } + + private static unsafe bool TryConvertWindowsIdToIanaId(string windowsId, string? region, bool allocate, out string? ianaId) + { + ianaId = null; + return false; + } +#pragma warning restore IDE0060 + } +} \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index e5a36bee754e9b..312a9734653793 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -231,7 +231,7 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return displayName; -#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI +#if TARGET_IOS || TARGET_TVOS return displayName; #else GetFullValueForDisplayNameField(Id, BaseUtcOffset, ref displayName); @@ -248,7 +248,7 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return standardDisplayName; -#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI +#if TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) return standardDisplayName; #endif @@ -266,7 +266,7 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return daylightDisplayName; -#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI +#if TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) return daylightDisplayName; #endif From 21acbca21ed07c25eda7e8993eaac18ccb7740f5 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 1 Sep 2023 15:15:29 +0200 Subject: [PATCH 06/14] Fix wasm build --- .../System.Private.CoreLib.Shared.projitems | 1 - ... TimeZoneInfo.MinimalGlobalizationData.cs} | 2 +- .../src/System/TimeZoneInfo.Unix.cs | 2 ++ .../pal_timeZoneInfo.m | 24 +++++++------------ 4 files changed, 12 insertions(+), 17 deletions(-) rename src/libraries/System.Private.CoreLib/src/System/{TimeZoneInfo.MinimalGlobalizationData.cs.cs => TimeZoneInfo.MinimalGlobalizationData.cs} (99%) diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 2b30fdc91f6bd8..f2601f6184967d 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -2476,7 +2476,6 @@ - diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs similarity index 99% rename from src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs.cs rename to src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs index b04b616d4f5db8..fa1d25e4933352 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.MinimalGlobalizationData.cs @@ -44,4 +44,4 @@ private static unsafe bool TryConvertWindowsIdToIanaId(string windowsId, string? } #pragma warning restore IDE0060 } -} \ No newline at end of file +} diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index 312a9734653793..521f7e361d9250 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -235,6 +235,7 @@ public AdjustmentRule[] GetAdjustmentRules() return displayName; #else GetFullValueForDisplayNameField(Id, BaseUtcOffset, ref displayName); + return displayName; #endif } @@ -271,6 +272,7 @@ public AdjustmentRule[] GetAdjustmentRules() return daylightDisplayName; #endif GetDaylightDisplayName(Id, ref daylightDisplayName); + return daylightDisplayName; } diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m index b9776af63fb636..b6e07ddd0b6ef4 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m @@ -38,42 +38,36 @@ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeN switch (type) { case TimeZoneDisplayName_Standard: - style = NSTimeZoneNameStyleStandard;//;NSTimeZoneNameStyleShortStandard + style = NSTimeZoneNameStyleStandard; break; case TimeZoneDisplayName_DaylightSavings: - style = NSTimeZoneNameStyleDaylightSaving;//;NSTimeZoneNameStyleShortDaylightSaving + style = NSTimeZoneNameStyleDaylightSaving; break; case TimeZoneDisplayName_Generic: - style = NSTimeZoneNameStyleGeneric;//;NSTimeZoneNameStyleShortGeneric + style = NSTimeZoneNameStyleGeneric; break; - // case TimeZoneDisplayName_GenericLocation: - // style = NSTimeZoneNameStyleStandard;//??? - // break; - // case TimeZoneDisplayName_ExemplarCity: - // style = NSTimeZoneNameStyleStandard;//?? - // break; default: - return UnknownError;//-1; + return UnknownError; } NSString* timeZoneName = [timeZone localizedName:style locale:currentLocale]; if (timeZoneName == NULL || timeZoneName.length == 0) { - return UnknownError;//0 + return UnknownError; } - int32_t index = 0, dstIdx = 0, isError = 0; + int32_t index = 0, dstIdx = 0, resultCode = Success; uint16_t dstCodepoint; while (index < timeZoneName.length) { dstCodepoint = [timeZoneName characterAtIndex: index]; - Append(result, dstIdx, resultLength, dstCodepoint, isError); + Append(result, dstIdx, resultLength, dstCodepoint, resultCode); index++; } dstCodepoint = '\0'; - Append(result, dstIdx, resultLength, dstCodepoint, isError); + Append(result, dstIdx, resultLength, dstCodepoint, resultCode); - return isError ? UnknownError : Success;//timeZoneName.length;//; + return resultCode; } } #endif From 4947b49852abad62337c15a0e96e7204e61e6756 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 1 Sep 2023 16:07:48 +0200 Subject: [PATCH 07/14] Minor fix --- .../src/System/TimeZoneInfo.FullGlobalizationData.cs | 4 ++-- src/libraries/System.Runtime/System.Runtime.sln | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs index 6c2e3a962526ec..b1cc58e3dd01d7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs @@ -9,7 +9,7 @@ public sealed partial class TimeZoneInfo { private static unsafe bool TryConvertIanaIdToWindowsId(string ianaId, bool allocate, out string? windowsId) { -#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI +#if TARGET_IOS || TARGET_TVOS windowsId = null; return false; #else @@ -37,7 +37,7 @@ ianaId is null || private static unsafe bool TryConvertWindowsIdToIanaId(string windowsId, string? region, bool allocate, out string? ianaId) { -#if TARGET_IOS || TARGET_TVOS || TARGET_BROWSER || TARGET_WASI +#if TARGET_IOS || TARGET_TVOS ianaId = null; return false; #else diff --git a/src/libraries/System.Runtime/System.Runtime.sln b/src/libraries/System.Runtime/System.Runtime.sln index 4ef7e0094581f3..a7d50d4a347abd 100644 --- a/src/libraries/System.Runtime/System.Runtime.sln +++ b/src/libraries/System.Runtime/System.Runtime.sln @@ -27,8 +27,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.Nls.Tests", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.Tests", "tests\System.Runtime.Tests.csproj", "{4EE36055-AD7C-4779-B3F6-08687960DCC3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.IOS.Tests", "tests\Hybrid\System.Runtime.IOS.Tests.csproj", "{4EE36055-AD7C-4779-B3F6-08687960DCC3}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.ReflectionInvokeEmit.Tests", "tests\System\Reflection\InvokeEmit\System.Runtime.ReflectionInvokeEmit.Tests.csproj", "{C3F25EEF-04B4-407A-960B-0C1CE9C04430}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.ReflectionInvokeInterpreted.Tests", "tests\System\Reflection\InvokeInterpreted\System.Runtime.ReflectionInvokeInterpreted.Tests.csproj", "{47E26787-7C27-4572-AD8B-868DE44E2C48}" From 32e90d83aeab0b7e5c71a41eaf0263cb291f4f6d Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 1 Sep 2023 16:27:41 +0200 Subject: [PATCH 08/14] Remove logging --- .../src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs | 1 - .../libs/System.Globalization.Native/pal_timeZoneInfo.m | 8 ++------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index aba934dfed64a9..8f9a0503bd7fcf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -28,7 +28,6 @@ public sealed partial class TimeZoneInfo // Helper function to get the standard display name for the UTC static time zone instance private static string GetUtcStandardDisplayName() { - System.Diagnostics.Debug.Write("TimeZoneInfo.GetUtcStandardDisplayName is called.\n"); #if TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) { diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m index b6e07ddd0b6ef4..dc3144a01a045f 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m @@ -2,22 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. // -#include -#include -#include - #include "pal_errors_internal.h" #include "pal_locale_internal.h" #include "pal_timeZoneInfo.h" - #import + #if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) /* Gets the localized display name that is currently in effect for the specified time zone. */ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* timeZoneId, int32_t timeZoneIdLength, - TimeZoneDisplayNameType type, uint16_t* result, int32_t resultLength) + TimeZoneDisplayNameType type, uint16_t* result, int32_t resultLength) { @autoreleasepool { From 88088d8a95a283583c464ab2bd2b650bcac089cc Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 5 Sep 2023 11:58:05 +0200 Subject: [PATCH 09/14] Fix failure on maccatalyst --- .../System/TimeZoneInfo.FullGlobalizationData.Unix.cs | 10 +++++----- .../src/System/TimeZoneInfo.FullGlobalizationData.cs | 4 ++-- .../src/System/TimeZoneInfo.Unix.NonAndroid.cs | 2 +- .../src/System/TimeZoneInfo.Unix.cs | 6 +++--- .../System.Runtime/tests/System/TimeZoneInfoTests.cs | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index 8f9a0503bd7fcf..3854243e4bb8d3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -28,7 +28,7 @@ public sealed partial class TimeZoneInfo // Helper function to get the standard display name for the UTC static time zone instance private static string GetUtcStandardDisplayName() { -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) { // For this target, be consistent with other time zone display names that use an abbreviation. @@ -55,7 +55,7 @@ private static string GetUtcStandardDisplayName() // Helper function to get the full display name for the UTC static time zone instance private static string GetUtcFullDisplayName(string timeZoneId, string standardDisplayName) { -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) { // For this target, be consistent with other time zone display names that use the ID. @@ -109,7 +109,7 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati { fixed (char* bufferPtr = buffer) { -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (GlobalizationMode.Hybrid) return Interop.Globalization.GetTimeZoneDisplayNameNative(locale, locale.Length, id, id.Length, type, bufferPtr, buffer.Length); #endif @@ -129,7 +129,7 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati { fixed (char* bufferPtr = buffer) { -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (GlobalizationMode.Hybrid) return Interop.Globalization.GetTimeZoneDisplayNameNative(locale, locale.Length, id, id.Length, type, bufferPtr, buffer.Length); #endif @@ -278,7 +278,7 @@ private static string GetExemplarCityName(string timeZoneId, string uiCultureNam // Helper function that returns an alternative ID using ICU data. Used primarily for converting from Windows IDs. private static unsafe string? GetAlternativeId(string id, out bool idIsIana) { -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS // No alternative IDs in this target. idIsIana = false; return null; diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs index b1cc58e3dd01d7..b79848bcd36109 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs @@ -9,7 +9,7 @@ public sealed partial class TimeZoneInfo { private static unsafe bool TryConvertIanaIdToWindowsId(string ianaId, bool allocate, out string? windowsId) { -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS windowsId = null; return false; #else @@ -37,7 +37,7 @@ ianaId is null || private static unsafe bool TryConvertWindowsIdToIanaId(string windowsId, string? region, bool allocate, out string? ianaId) { -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS ianaId = null; return false; #else diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs index f90b52bdc52053..885acc9cef882c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs @@ -511,7 +511,7 @@ private static bool TryGetLocalTzFile([NotNullWhen(true)] out byte[]? rawData, [ #pragma warning disable IDE0074 // Use compound assignment if (tzVariable == null) { -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS tzVariable = Interop.Sys.GetDefaultTimeZone(); #elif TARGET_WASI || TARGET_BROWSER if (UseEmbeddedTzDatabase) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index 521f7e361d9250..967a01aaaf8072 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -231,7 +231,7 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return displayName; -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS return displayName; #else GetFullValueForDisplayNameField(Id, BaseUtcOffset, ref displayName); @@ -249,7 +249,7 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return standardDisplayName; -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) return standardDisplayName; #endif @@ -267,7 +267,7 @@ public AdjustmentRule[] GetAdjustmentRules() if (GlobalizationMode.Invariant) return daylightDisplayName; -#if TARGET_IOS || TARGET_TVOS +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (!GlobalizationMode.Hybrid) return daylightDisplayName; #endif diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index c44010cf2618ca..d70407ffb5b274 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -89,7 +89,7 @@ public static void Names() // Name abbreviations, if available, are used instead public static IEnumerable Platform_TimeZoneNamesTestData() { - if (PlatformDetection.IsBrowser || (!PlatformDetection.IsHybridGlobalizationOnOSX && (PlatformDetection.IsiOS || PlatformDetection.IstvOS))) + if (PlatformDetection.IsBrowser || (!PlatformDetection.IsHybridGlobalizationOnOSX && (PlatformDetection.IsMacCatalyst || PlatformDetection.IsiOS || PlatformDetection.IstvOS))) return new TheoryData { { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) America/Los_Angeles", null, "PST", "PDT" }, @@ -100,7 +100,7 @@ public static IEnumerable Platform_TimeZoneNamesTestData() { s_NewfoundlandTz, "(UTC-03:30) America/St_Johns", null, "NST", "NDT" }, { s_catamarcaTz, "(UTC-03:00) America/Argentina/Catamarca", null, "-03", "-02" } }; - else if(PlatformDetection.IsHybridGlobalizationOnOSX && (PlatformDetection.IsiOS || PlatformDetection.IstvOS)) + else if (PlatformDetection.IsHybridGlobalizationOnOSX && (PlatformDetection.IsMacCatalyst || PlatformDetection.IsiOS || PlatformDetection.IstvOS)) return new TheoryData { { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) America/Los_Angeles", null, "Pacific Standard Time", "Pacific Daylight Time" }, From a886791658256f64fb664471fdcd00f0ebd91e41 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 5 Sep 2023 18:38:18 +0200 Subject: [PATCH 10/14] Changed displayName for hybrid mode --- .../Interop.TimeZoneDisplayNameType.cs | 1 + ...TimeZoneInfo.FullGlobalizationData.Unix.cs | 20 ++++-- .../src/System/TimeZoneInfo.Unix.cs | 6 +- .../tests/System/TimeZoneInfoTests.cs | 4 +- .../pal_normalization.m | 4 ++ .../pal_timeZoneInfo.h | 1 + .../pal_timeZoneInfo.m | 61 +++++++++++-------- 7 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/libraries/Common/src/Interop/Interop.TimeZoneDisplayNameType.cs b/src/libraries/Common/src/Interop/Interop.TimeZoneDisplayNameType.cs index 570eb0eb4b1ecd..698cdd54aebdf7 100644 --- a/src/libraries/Common/src/Interop/Interop.TimeZoneDisplayNameType.cs +++ b/src/libraries/Common/src/Interop/Interop.TimeZoneDisplayNameType.cs @@ -13,6 +13,7 @@ internal enum TimeZoneDisplayNameType DaylightSavings = 2, GenericLocation = 3, ExemplarCity = 4, + TimeZoneName = 5, } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index 3854243e4bb8d3..e88430c3fb6dfc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -153,13 +153,27 @@ private static unsafe void GetDisplayName(string timeZoneId, Interop.Globalizati // Helper function that builds the value backing the DisplayName field from globalization data. private static void GetFullValueForDisplayNameField(string timeZoneId, TimeSpan baseUtcOffset, ref string? displayName) { + CultureInfo uiCulture = UICulture; + // Get the base offset to prefix in front of the time zone. + // Only UTC and its aliases have "(UTC)", handled earlier. All other zones include an offset, even if it's zero. + string baseOffsetText = string.Create(null, stackalloc char[128], $"(UTC{(baseUtcOffset >= TimeSpan.Zero ? '+' : '-')}{baseUtcOffset:hh\\:mm})"); + +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + { + string? timeZoneName = null; + GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.TimeZoneName, uiCulture.Name, ref timeZoneName); + // For this target, be consistent with other time zone display names that use the ID. + displayName = $"{baseOffsetText} {timeZoneName}"; + return; + } +#endif // There are a few different ways we might show the display name depending on the data. // The algorithm used below should avoid duplicating the same words while still achieving the // goal of providing a unique, discoverable, and intuitive name. // Try to get the generic name for this time zone. string? genericName = null; - CultureInfo uiCulture = UICulture; GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.Generic, uiCulture.Name, ref genericName); if (genericName == null) { @@ -167,10 +181,6 @@ private static void GetFullValueForDisplayNameField(string timeZoneId, TimeSpan return; } - // Get the base offset to prefix in front of the time zone. - // Only UTC and its aliases have "(UTC)", handled earlier. All other zones include an offset, even if it's zero. - string baseOffsetText = string.Create(null, stackalloc char[128], $"(UTC{(baseUtcOffset >= TimeSpan.Zero ? '+' : '-')}{baseUtcOffset:hh\\:mm})"); - // Get the generic location name. string? genericLocationName = null; GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.GenericLocation, uiCulture.Name, ref genericLocationName); diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index 967a01aaaf8072..d6b370b7210a60 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -232,12 +232,12 @@ public AdjustmentRule[] GetAdjustmentRules() return displayName; #if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS - return displayName; -#else + if (!GlobalizationMode.Hybrid) + return displayName; +#endif GetFullValueForDisplayNameField(Id, BaseUtcOffset, ref displayName); return displayName; -#endif } private string? PopulateStandardDisplayName() diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index d70407ffb5b274..88ea3476b4f2ed 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -88,7 +88,7 @@ public static void Names() // Due to ICU size limitations, full daylight/standard names are not included for the browser. // Name abbreviations, if available, are used instead public static IEnumerable Platform_TimeZoneNamesTestData() - { + {// if (PlatformDetection.IsBrowser || (!PlatformDetection.IsHybridGlobalizationOnOSX && (PlatformDetection.IsMacCatalyst || PlatformDetection.IsiOS || PlatformDetection.IstvOS))) return new TheoryData { @@ -147,7 +147,7 @@ public static void Platform_TimeZoneNames(TimeZoneInfo tzi, string displayName, displayName = displayName.Replace(c.ToString(), "", StringComparison.Ordinal); } } - + System.Diagnostics.Debug.WriteLine($"Platform_TimeZoneNames Display Name: '{tzi.DisplayName}'"); Assert.True(displayName == tzi.DisplayName || alternativeDisplayName == tzi.DisplayName, $"Display Name: Neither '{displayName}' nor '{alternativeDisplayName}' equal to '{tzi.DisplayName}'"); Assert.Equal(standardName, tzi.StandardName); diff --git a/src/native/libs/System.Globalization.Native/pal_normalization.m b/src/native/libs/System.Globalization.Native/pal_normalization.m index c31242ca36ef31..62c3ecde53c9d0 100644 --- a/src/native/libs/System.Globalization.Native/pal_normalization.m +++ b/src/native/libs/System.Globalization.Native/pal_normalization.m @@ -7,6 +7,10 @@ #include "pal_normalization.h" #import +#if !__has_feature(objc_arc) +#error This file relies on ARC for memory management, but ARC is not enabled. +#endif + #if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) static NSString* GetNormalizedStringForForm(NormalizationForm normalizationForm, NSString* sourceString) { diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h index 28a00e89186a77..99653b939196e2 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.h @@ -18,6 +18,7 @@ typedef enum TimeZoneDisplayName_DaylightSavings = 2, TimeZoneDisplayName_GenericLocation = 3, TimeZoneDisplayName_ExemplarCity = 4, + TimeZoneDisplayName_TimeZoneName = 5, } TimeZoneDisplayNameType; PALEXPORT int32_t GlobalizationNative_WindowsIdToIanaId(const UChar* windowsId, const char* region, UChar* ianaId, int32_t ianaIdLength); diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m index dc3144a01a045f..5eb3d736f405fc 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m @@ -7,6 +7,10 @@ #include "pal_timeZoneInfo.h" #import +#if !__has_feature(objc_arc) +#error This file relies on ARC for memory management, but ARC is not enabled. +#endif + #if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) /* @@ -17,36 +21,43 @@ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeN { @autoreleasepool { - NSLocale *currentLocale; - if(localeName == NULL || lNameLength == 0) - { - currentLocale = [NSLocale systemLocale]; - } - else - { - NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength]; - currentLocale = [NSLocale localeWithLocaleIdentifier:locName]; - } NSString* tzName = [NSString stringWithCharacters: timeZoneId length: timeZoneIdLength]; NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:tzName]; - NSTimeZoneNameStyle style; + NSString* timeZoneName; - switch (type) + if (type == TimeZoneDisplayName_TimeZoneName) + timeZoneName = timeZone.name; + else { - case TimeZoneDisplayName_Standard: - style = NSTimeZoneNameStyleStandard; - break; - case TimeZoneDisplayName_DaylightSavings: - style = NSTimeZoneNameStyleDaylightSaving; - break; - case TimeZoneDisplayName_Generic: - style = NSTimeZoneNameStyleGeneric; - break; - default: - return UnknownError; - } + NSLocale *currentLocale; + if(localeName == NULL || lNameLength == 0) + { + currentLocale = [NSLocale systemLocale]; + } + else + { + NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength]; + currentLocale = [NSLocale localeWithLocaleIdentifier:locName]; + } + NSTimeZoneNameStyle style; - NSString* timeZoneName = [timeZone localizedName:style locale:currentLocale]; + switch (type) + { + case TimeZoneDisplayName_Standard: + style = NSTimeZoneNameStyleStandard; + break; + case TimeZoneDisplayName_DaylightSavings: + style = NSTimeZoneNameStyleDaylightSaving; + break; + case TimeZoneDisplayName_Generic: + style = NSTimeZoneNameStyleGeneric; + break; + default: + return UnknownError; + } + + timeZoneName = [timeZone localizedName:style locale:currentLocale]; + } if (timeZoneName == NULL || timeZoneName.length == 0) { return UnknownError; From 8d9143034eb090a8453639dae80935d0c05fca73 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 5 Sep 2023 18:48:49 +0200 Subject: [PATCH 11/14] Remove logs --- .../System.Runtime/tests/System/TimeZoneInfoTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 88ea3476b4f2ed..d70407ffb5b274 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -88,7 +88,7 @@ public static void Names() // Due to ICU size limitations, full daylight/standard names are not included for the browser. // Name abbreviations, if available, are used instead public static IEnumerable Platform_TimeZoneNamesTestData() - {// + { if (PlatformDetection.IsBrowser || (!PlatformDetection.IsHybridGlobalizationOnOSX && (PlatformDetection.IsMacCatalyst || PlatformDetection.IsiOS || PlatformDetection.IstvOS))) return new TheoryData { @@ -147,7 +147,7 @@ public static void Platform_TimeZoneNames(TimeZoneInfo tzi, string displayName, displayName = displayName.Replace(c.ToString(), "", StringComparison.Ordinal); } } - System.Diagnostics.Debug.WriteLine($"Platform_TimeZoneNames Display Name: '{tzi.DisplayName}'"); + Assert.True(displayName == tzi.DisplayName || alternativeDisplayName == tzi.DisplayName, $"Display Name: Neither '{displayName}' nor '{alternativeDisplayName}' equal to '{tzi.DisplayName}'"); Assert.Equal(standardName, tzi.StandardName); From 4d9b1f6adb364c448b423309794f332798f8f8fe Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 6 Sep 2023 10:43:45 +0200 Subject: [PATCH 12/14] Changes requested by review --- ...TimeZoneInfo.FullGlobalizationData.Unix.cs | 19 ++++++++++--------- .../pal_timeZoneInfo.m | 6 ++++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index e88430c3fb6dfc..693a6ad187ebf4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -11,6 +11,7 @@ public sealed partial class TimeZoneInfo { private const string InvariantUtcStandardDisplayName = "Coordinated Universal Time"; private const string FallbackCultureName = "en-US"; +#if !TARGET_MACCATALYST && TARGET_IOS && TARGET_TVOS private const string GmtId = "GMT"; // Some time zones may give better display names using their location names rather than their generic name. @@ -22,6 +23,7 @@ public sealed partial class TimeZoneInfo "Pacific/Apia", // Prefer "Samoa Time" over "Apia Time" "Pacific/Pitcairn" // Prefer "Pitcairn Islands Time" over "Pitcairn Time" }; +#endif private static CultureInfo? _uiCulture; @@ -159,15 +161,13 @@ private static void GetFullValueForDisplayNameField(string timeZoneId, TimeSpan string baseOffsetText = string.Create(null, stackalloc char[128], $"(UTC{(baseUtcOffset >= TimeSpan.Zero ? '+' : '-')}{baseUtcOffset:hh\\:mm})"); #if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS - if (GlobalizationMode.Hybrid) - { - string? timeZoneName = null; - GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.TimeZoneName, uiCulture.Name, ref timeZoneName); - // For this target, be consistent with other time zone display names that use the ID. - displayName = $"{baseOffsetText} {timeZoneName}"; - return; - } -#endif + Debug.Assert(GlobalizationMode.Hybrid); + string? timeZoneName = null; + GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.TimeZoneName, uiCulture.Name, ref timeZoneName); + // For this target, be consistent with other time zone display names that use the ID. + displayName = $"{baseOffsetText} {timeZoneName}"; + return; +#else // There are a few different ways we might show the display name depending on the data. // The algorithm used below should avoid duplicating the same words while still achieving the // goal of providing a unique, discoverable, and intuitive name. @@ -267,6 +267,7 @@ private static void GetFullValueForDisplayNameField(string timeZoneId, TimeSpan displayName = $"{baseOffsetText} {genericName} ({exemplarCityName})"; } +#endif } // Helper function that gets an exmplar city name either from ICU or from the IANA time zone ID itself diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m index 5eb3d736f405fc..d05c6fa9eebe7b 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m @@ -3,7 +3,7 @@ // #include "pal_errors_internal.h" -#include "pal_locale_internal.h" +#include "pal_icushim_internal.h" #include "pal_timeZoneInfo.h" #import @@ -30,7 +30,7 @@ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeN else { NSLocale *currentLocale; - if(localeName == NULL || lNameLength == 0) + if (localeName == NULL || lNameLength == 0) { currentLocale = [NSLocale systemLocale]; } @@ -69,6 +69,8 @@ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeN { dstCodepoint = [timeZoneName characterAtIndex: index]; Append(result, dstIdx, resultLength, dstCodepoint, resultCode); + if (resultCode != Success) + return resultCode; index++; } dstCodepoint = '\0'; From a64ee2b509f02a8d59b234759580a5ed6c0cede2 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 6 Sep 2023 13:29:46 +0200 Subject: [PATCH 13/14] Fix build failure --- .../src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index 693a6ad187ebf4..9d69737220fc6e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -11,7 +11,7 @@ public sealed partial class TimeZoneInfo { private const string InvariantUtcStandardDisplayName = "Coordinated Universal Time"; private const string FallbackCultureName = "en-US"; -#if !TARGET_MACCATALYST && TARGET_IOS && TARGET_TVOS +#if !TARGET_MACCATALYST && !TARGET_IOS && !TARGET_TVOS private const string GmtId = "GMT"; // Some time zones may give better display names using their location names rather than their generic name. From c589bbef27b3447271313dba975d6bfedc626dd1 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 6 Sep 2023 17:48:18 +0200 Subject: [PATCH 14/14] Add checks and remove not needed code --- .../src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs | 6 ------ .../src/System/TimeZoneInfo.FullGlobalizationData.cs | 4 ++-- .../libs/System.Globalization.Native/pal_timeZoneInfo.m | 4 ++++ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index 9d69737220fc6e..1703114fabea37 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -289,14 +289,8 @@ private static string GetExemplarCityName(string timeZoneId, string uiCultureNam // Helper function that returns an alternative ID using ICU data. Used primarily for converting from Windows IDs. private static unsafe string? GetAlternativeId(string id, out bool idIsIana) { -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS - // No alternative IDs in this target. - idIsIana = false; - return null; -#else idIsIana = false; return TryConvertWindowsIdToIanaId(id, null, out string? ianaId) ? ianaId : null; -#endif } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs index b79848bcd36109..06bffad9f31515 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs @@ -10,8 +10,8 @@ public sealed partial class TimeZoneInfo private static unsafe bool TryConvertIanaIdToWindowsId(string ianaId, bool allocate, out string? windowsId) { #if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS - windowsId = null; - return false; + windowsId = null; + return false; #else if (GlobalizationMode.Invariant || GlobalizationMode.UseNls || diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m index d05c6fa9eebe7b..1cd51dc6704ffd 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m @@ -23,6 +23,10 @@ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeN { NSString* tzName = [NSString stringWithCharacters: timeZoneId length: timeZoneIdLength]; NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:tzName]; + if (timeZone == NULL) + { + return UnknownError; + } NSString* timeZoneName; if (type == TimeZoneDisplayName_TimeZoneName)