From 0b8305791953e0d06053eed093b536c1c0e80f42 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Wed, 12 Jul 2023 16:15:45 -0400 Subject: [PATCH] [libs][TimeZoneInfo] Add switch for unsorted GetSystemTimeZones --- .../src/System/TimeZoneInfo.cs | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs index 583212906e68c..ee0d263420bff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs @@ -33,6 +33,7 @@ internal enum TimeZoneInfoOptions [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed partial class TimeZoneInfo : IEquatable, ISerializable, IDeserializationCallback { + internal static bool Unsorted { get; } = AppContextConfigHelper.GetBooleanConfig("System.TimeZoneInfo.SystemTimeZonesUnsorted", "DOTNET_SYSTEM_TIME_ZONE_INFO_SYSTEM_TIME_ZONES_UNSORTED"); private enum TimeZoneInfoResult { Success = 0, @@ -133,6 +134,7 @@ public DateTimeKind GetCorrespondingKind(TimeZoneInfo? timeZone) public ReadOnlyCollection? _readOnlySystemTimeZones; public Dictionary? _timeZonesUsingAlternativeIds; public bool _allSystemTimeZonesRead; + public bool _systemTimeZonesSorted; } // used by GetUtcOffsetFromUtc (DateTime.Now, DateTime.ToLocalTime) for max/min whole-day range checks @@ -886,31 +888,43 @@ public static ReadOnlyCollection GetSystemTimeZones() lock (cachedData) { + if (cachedData._systemTimeZonesSorted) + { + Debug.Assert(cachedData._readOnlySystemTimeZones != null); + return cachedData._readOnlySystemTimeZones; + } + if (cachedData._readOnlySystemTimeZones == null) { PopulateAllSystemTimeZones(cachedData); cachedData._allSystemTimeZonesRead = true; + } - if (cachedData._systemTimeZones != null) - { - // return a collection of the cached system time zones - TimeZoneInfo[] array = new TimeZoneInfo[cachedData._systemTimeZones.Count]; - cachedData._systemTimeZones.Values.CopyTo(array, 0); - - // sort and copy the TimeZoneInfo's into a ReadOnlyCollection for the user - Array.Sort(array, static (x, y) => - { - // sort by BaseUtcOffset first and by DisplayName second - this is similar to the Windows Date/Time control panel - int comparison = x.BaseUtcOffset.CompareTo(y.BaseUtcOffset); - return comparison == 0 ? string.CompareOrdinal(x.DisplayName, y.DisplayName) : comparison; - }); + if (cachedData._systemTimeZones == null) + { + cachedData._readOnlySystemTimeZones = ReadOnlyCollection.Empty; + } + else if (Unsorted) + { + List unsortedSystemTimeZones = new List(cachedData._systemTimeZones.Values); + cachedData._readOnlySystemTimeZones = new ReadOnlyCollection(unsortedSystemTimeZones); + } + else + { + cachedData._systemTimeZonesSorted = true; + // return a collection of the cached system time zones + TimeZoneInfo[] array = new TimeZoneInfo[cachedData._systemTimeZones.Count]; + cachedData._systemTimeZones.Values.CopyTo(array, 0); - cachedData._readOnlySystemTimeZones = new ReadOnlyCollection(array); - } - else + // sort and copy the TimeZoneInfo's into a ReadOnlyCollection for the user + Array.Sort(array, static (x, y) => { - cachedData._readOnlySystemTimeZones = ReadOnlyCollection.Empty; - } + // sort by BaseUtcOffset first and by DisplayName second - this is similar to the Windows Date/Time control panel + int comparison = x.BaseUtcOffset.CompareTo(y.BaseUtcOffset); + return comparison == 0 ? string.CompareOrdinal(x.DisplayName, y.DisplayName) : comparison; + }); + + cachedData._readOnlySystemTimeZones = new ReadOnlyCollection(array); } }