From e08f971cf31e102c6f62e874e9914f4d8d72ce8b Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Wed, 19 Jan 2022 17:30:25 -0500 Subject: [PATCH 01/13] [libraries][Android] Filter out backward timezone IDs using tzlookup on Android --- .../src/Resources/Strings.resx | 6 ++ .../src/System/TimeZoneInfo.Unix.Android.cs | 87 ++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index f98789424343b4..ccc2854eaf7543 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -2593,6 +2593,9 @@ The Timer was already closed using an incompatible Dispose method. + + Internal Error in parsing tzlookup file {1}. + The given type cannot be boxed. @@ -3025,6 +3028,9 @@ The operation was canceled. + + There is insufficient memory to allocate a buffer to read tzlookup file {1}. + Value was either too large or too small for an unsigned byte. diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs index 53baf4eb65111f..95c8cdc7785f90 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs @@ -195,6 +195,7 @@ private sealed class AndroidTzData private int[] _lengths; private string _tzFileDir; private string _tzFilePath; + private bool _isFiltered; private static string GetApexTimeDataRoot() { @@ -234,6 +235,7 @@ public AndroidTzData() { _tzFileDir = tzFileDir; _tzFilePath = tzFilePath; + _isFiltered = false; return; } } @@ -241,6 +243,86 @@ public AndroidTzData() throw new TimeZoneNotFoundException(SR.TimeZoneNotFound_ValidTimeZoneFileMissing); } + // On some versions of Android, the tzdata file may still contain backward timezone ids. + // We attempt to use tzlookup.xml, which is available on some versions of Android to help + // validate non-backward timezone ids + // tzlookup.xml is an autogenerated file that contains timezone ids in this form: + // + // + // + // + // Australia/Sydney + // ... + // ... + // Australia/Eucla + // + // + // ... + // ... + // ... + // + // + // + // + // Once the timezone cache is populated with the IDs, we reference tzlookup id tags and + // remove IDs and their associated information (byteoffsets and lengths) from the current + // AndroidTzData instance. + private void filterBackwardIDs(string lookupPath) + { + try + { + using (StreamReader sr = File.OpenText(lookupPath)) + { + var tzLookupIDs = new HashSet(); + string? tzLookupLine; + while (sr.Peek() >= 0) + { + if (!(tzLookupLine = sr.ReadLine())!.TrimStart().StartsWith("')+1; + int idLength = tzLookupLine.IndexOf(" or the end tag are not found + continue; + } + string id = tzLookupLine.Substring(idStart, idLength); + tzLookupIDs.Add(id); + } + var cleanIDs = new List(); + var cleanOffsets = new List(); + var cleanLengths = new List(); + for (int i = 0; i < _ids.GetLength(0); ++i) + { + if (tzLookupIDs.Contains(_ids[i])) + { + cleanIDs.Add(_ids[i]); + cleanOffsets.Add(_byteOffsets[i]); + cleanLengths.Add(_lengths[i]); + } + } + _ids = cleanIDs.ToArray(); + _byteOffsets = cleanOffsets.ToArray(); + _lengths = cleanLengths.ToArray(); + } + } + catch (FileNotFoundException) + { + // Some versions of Android will not have tzlookup.xml, so just warn that there may be backward timezone IDs + } + catch (IOException) + { + throw new InvalidOperationException(SR.Format(SR.InvalidOperation_TimeZoneLookupParsing, lookupPath)); + } + catch (OutOfMemoryException) + { + throw new OutOfMemoryException(SR.Format(SR.OutOfMemory_TimeZoneLookupParsing, lookupPath)); + } + + _isFiltered = true; + } + [MemberNotNullWhen(true, nameof(_ids))] [MemberNotNullWhen(true, nameof(_byteOffsets))] [MemberNotNullWhen(true, nameof(_lengths))] @@ -258,7 +340,7 @@ private bool LoadData(string path) } return true; } - catch {} + catch {} // TODO add warning return false; } @@ -308,7 +390,6 @@ private void ReadIndex(Stream fs, int indexOffset, int dataOffset) int indexSize = dataOffset - indexOffset; const int entrySize = 52; // Data entry size int entryCount = indexSize / entrySize; - _byteOffsets = new int[entryCount]; _ids = new string[entryCount]; _lengths = new int[entryCount]; @@ -372,6 +453,8 @@ private void LoadEntryAt(Stream fs, long position, out string id, out int byteOf public string[] GetTimeZoneIds() { + if (!_isFiltered) + filterBackwardIDs(Path.Combine(_tzFileDir, "tzlookup.xml")); return _ids; } From 7258e39ca517ef50a6f2191a0acd01acdcc969fb Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Wed, 19 Jan 2022 21:20:58 -0500 Subject: [PATCH 02/13] [tests] Add TimeZoneInfo Test to detect Backward TimeZones --- .../tests/System/TimeZoneInfoTests.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index b352a529d6b009..5754fcc69829c4 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -2921,6 +2921,19 @@ public static void AdjustmentRuleBaseUtcOffsetDeltaTest() Assert.Equal(new TimeSpan(2, 0, 0), customTimeZone.GetUtcOffset(new DateTime(2021, 3, 10, 2, 0, 0))); } + [Fact] + public static void NoBackwardTimeZones() + { + ReadOnlyCollection tzCollection = TimeZoneInfo.GetSystemTimeZones(); + HashSet tzDisplayNames = new HashSet(); + + foreach (TimeZoneInfo timezone in tzCollection) + { + tzDisplayNames.Add(timezone.DisplayName); + } + Assert.Equal(tzCollection.Count, tzDisplayNames.Count); + } + private static bool IsEnglishUILanguage => CultureInfo.CurrentUICulture.Name.Length == 0 || CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "en"; private static bool IsEnglishUILanguageAndRemoteExecutorSupported => IsEnglishUILanguage && RemoteExecutor.IsSupported; From 3c86169f13539aa6c8191c4c9895322207430b45 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Wed, 19 Jan 2022 21:57:50 -0500 Subject: [PATCH 03/13] Address feedback --- .../System.Private.CoreLib/src/Resources/Strings.resx | 4 ++-- .../src/System/TimeZoneInfo.Unix.Android.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index ccc2854eaf7543..e34b019fef5a70 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -2594,7 +2594,7 @@ The Timer was already closed using an incompatible Dispose method. - Internal Error in parsing tzlookup file {1}. + Internal Error in parsing tzlookup file "{1}". The given type cannot be boxed. @@ -3029,7 +3029,7 @@ The operation was canceled. - There is insufficient memory to allocate a buffer to read tzlookup file {1}. + There is insufficient memory to allocate a buffer to read tzlookup file "{1}". Value was either too large or too small for an unsigned byte. diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs index 95c8cdc7785f90..f30e1be9e4a412 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs @@ -267,7 +267,7 @@ public AndroidTzData() // Once the timezone cache is populated with the IDs, we reference tzlookup id tags and // remove IDs and their associated information (byteoffsets and lengths) from the current // AndroidTzData instance. - private void filterBackwardIDs(string lookupPath) + private void FilterBackwardIDs(string lookupPath) { try { @@ -280,8 +280,8 @@ private void filterBackwardIDs(string lookupPath) if (!(tzLookupLine = sr.ReadLine())!.TrimStart().StartsWith("')+1; - int idLength = tzLookupLine.IndexOf("') + 1; + int idLength = tzLookupLine.LastIndexOf(" or the end tag are not found @@ -454,7 +454,7 @@ private void LoadEntryAt(Stream fs, long position, out string id, out int byteOf public string[] GetTimeZoneIds() { if (!_isFiltered) - filterBackwardIDs(Path.Combine(_tzFileDir, "tzlookup.xml")); + FilterBackwardIDs(Path.Combine(_tzFileDir, "tzlookup.xml")); return _ids; } From 9f6adcef242b5dd0a069ffe7681f13a3d4b23f16 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Thu, 20 Jan 2022 13:26:15 -0500 Subject: [PATCH 04/13] Address more feedback Use StringComparison.Ordinal for strings Catch and ignore exceptions skip if indexof returns less than -1 --- .../src/System/TimeZoneInfo.Unix.Android.cs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs index f30e1be9e4a412..f139ba63883951 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs @@ -277,12 +277,12 @@ private void FilterBackwardIDs(string lookupPath) string? tzLookupLine; while (sr.Peek() >= 0) { - if (!(tzLookupLine = sr.ReadLine())!.TrimStart().StartsWith("') + 1; - int idLength = tzLookupLine.LastIndexOf(" or the end tag are not found continue; @@ -307,18 +307,7 @@ private void FilterBackwardIDs(string lookupPath) _lengths = cleanLengths.ToArray(); } } - catch (FileNotFoundException) - { - // Some versions of Android will not have tzlookup.xml, so just warn that there may be backward timezone IDs - } - catch (IOException) - { - throw new InvalidOperationException(SR.Format(SR.InvalidOperation_TimeZoneLookupParsing, lookupPath)); - } - catch (OutOfMemoryException) - { - throw new OutOfMemoryException(SR.Format(SR.OutOfMemory_TimeZoneLookupParsing, lookupPath)); - } + catch {} _isFiltered = true; } From 602201fc290dbf418df90d25a46884113ecffad4 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Thu, 20 Jan 2022 17:22:05 -0500 Subject: [PATCH 05/13] [libraries][Android] Add isBackwards in lieu of removing timezone ids --- .../src/System/TimeZoneInfo.Unix.Android.cs | 66 ++++++++----------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs index f139ba63883951..bbeee7ebbd4631 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs @@ -193,9 +193,9 @@ private sealed class AndroidTzData private string[] _ids; private int[] _byteOffsets; private int[] _lengths; + private bool[] _isBackwards; private string _tzFileDir; private string _tzFilePath; - private bool _isFiltered; private static string GetApexTimeDataRoot() { @@ -231,11 +231,10 @@ public AndroidTzData() foreach (var tzFileDir in tzFileDirList) { string tzFilePath = Path.Combine(tzFileDir, TimeZoneFileName); - if (LoadData(tzFilePath)) + if (LoadData(tzFileDir, tzFilePath)) { _tzFileDir = tzFileDir; _tzFilePath = tzFilePath; - _isFiltered = false; return; } } @@ -264,23 +263,22 @@ public AndroidTzData() // // // - // Once the timezone cache is populated with the IDs, we reference tzlookup id tags and - // remove IDs and their associated information (byteoffsets and lengths) from the current - // AndroidTzData instance. - private void FilterBackwardIDs(string lookupPath) + // Once the timezone cache is populated with the IDs, we reference tzlookup id tags + // to determine if an id is backwards and label it as such if they are. + private void FilterBackwardIDs(string tzFileDir, out HashSet tzLookupIDs) { + tzLookupIDs = new HashSet(); try { - using (StreamReader sr = File.OpenText(lookupPath)) + using (StreamReader sr = File.OpenText(Path.Combine(tzFileDir, "tzlookup.xml"))) { - var tzLookupIDs = new HashSet(); string? tzLookupLine; while (sr.Peek() >= 0) { - if (!(tzLookupLine = sr.ReadLine())!.TrimStart().StartsWith("') + 1; + int idStart = tzLookupLine!.IndexOf('>') + 1; int idLength = tzLookupLine.LastIndexOf("(); - var cleanOffsets = new List(); - var cleanLengths = new List(); - for (int i = 0; i < _ids.GetLength(0); ++i) - { - if (tzLookupIDs.Contains(_ids[i])) - { - cleanIDs.Add(_ids[i]); - cleanOffsets.Add(_byteOffsets[i]); - cleanLengths.Add(_lengths[i]); - } - } - _ids = cleanIDs.ToArray(); - _byteOffsets = cleanOffsets.ToArray(); - _lengths = cleanLengths.ToArray(); } } catch {} - - _isFiltered = true; } [MemberNotNullWhen(true, nameof(_ids))] [MemberNotNullWhen(true, nameof(_byteOffsets))] [MemberNotNullWhen(true, nameof(_lengths))] - private bool LoadData(string path) + [MemberNotNullWhen(true, nameof(_isBackwards))] + private bool LoadData(string tzFileDir, string path) { if (!File.Exists(path)) { @@ -325,7 +307,7 @@ private bool LoadData(string path) { using (FileStream fs = File.OpenRead(path)) { - LoadTzFile(fs); + LoadTzFile(tzFileDir, fs); } return true; } @@ -337,7 +319,8 @@ private bool LoadData(string path) [MemberNotNull(nameof(_ids))] [MemberNotNull(nameof(_byteOffsets))] [MemberNotNull(nameof(_lengths))] - private void LoadTzFile(Stream fs) + [MemberNotNull(nameof(_isBackwards))] + private void LoadTzFile(string tzFileDir, Stream fs) { const int HeaderSize = 24; Span buffer = stackalloc byte[HeaderSize]; @@ -345,7 +328,7 @@ private void LoadTzFile(Stream fs) ReadTzDataIntoBuffer(fs, 0, buffer); LoadHeader(buffer, out int indexOffset, out int dataOffset); - ReadIndex(fs, indexOffset, dataOffset); + ReadIndex(tzFileDir, fs, indexOffset, dataOffset); } private void LoadHeader(Span buffer, out int indexOffset, out int dataOffset) @@ -374,7 +357,8 @@ private void LoadHeader(Span buffer, out int indexOffset, out int dataOffs [MemberNotNull(nameof(_ids))] [MemberNotNull(nameof(_byteOffsets))] [MemberNotNull(nameof(_lengths))] - private void ReadIndex(Stream fs, int indexOffset, int dataOffset) + [MemberNotNull(nameof(_isBackwards))] + private void ReadIndex(string tzFileDir, Stream fs, int indexOffset, int dataOffset) { int indexSize = dataOffset - indexOffset; const int entrySize = 52; // Data entry size @@ -382,7 +366,8 @@ private void ReadIndex(Stream fs, int indexOffset, int dataOffset) _byteOffsets = new int[entryCount]; _ids = new string[entryCount]; _lengths = new int[entryCount]; - + _isBackwards = new bool[entryCount]; + FilterBackwardIDs(tzFileDir, out HashSet tzLookupIDs); for (int i = 0; i < entryCount; ++i) { LoadEntryAt(fs, indexOffset + (entrySize*i), out string id, out int byteOffset, out int length); @@ -390,6 +375,7 @@ private void ReadIndex(Stream fs, int indexOffset, int dataOffset) _byteOffsets[i] = byteOffset + dataOffset; _ids[i] = id; _lengths[i] = length; + _isBackwards[i] = !tzLookupIDs.Contains(id); if (length < 24) // Header Size { @@ -442,9 +428,15 @@ private void LoadEntryAt(Stream fs, long position, out string id, out int byteOf public string[] GetTimeZoneIds() { - if (!_isFiltered) - FilterBackwardIDs(Path.Combine(_tzFileDir, "tzlookup.xml")); - return _ids; + List nonBackwardsTZIDs = new List(); + for (int i = 0; i < _ids.Length; i++) + { + if (!_isBackwards[i]) + { + nonBackwardsTZIDs.Add(_ids[i]); + } + } + return nonBackwardsTZIDs.ToArray(); } public string GetTimeZoneDirectory() From 86a56b8c1e741541bab46ccb111b6e4845dded07 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Thu, 20 Jan 2022 19:57:14 -0500 Subject: [PATCH 06/13] Remove unneeded strings.resx additions --- .../System.Private.CoreLib/src/Resources/Strings.resx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index e34b019fef5a70..f98789424343b4 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -2593,9 +2593,6 @@ The Timer was already closed using an incompatible Dispose method. - - Internal Error in parsing tzlookup file "{1}". - The given type cannot be boxed. @@ -3028,9 +3025,6 @@ The operation was canceled. - - There is insufficient memory to allocate a buffer to read tzlookup file "{1}". - Value was either too large or too small for an unsigned byte. From ec59f2550fb56ec8456055d974c145ea2513fcb9 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Thu, 20 Jan 2022 20:02:27 -0500 Subject: [PATCH 07/13] Temporarily show timezone displayNames in NoBackwardTimeZones --- .../System.Runtime/tests/System/TimeZoneInfoTests.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 5754fcc69829c4..aa35f2cc14094e 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -2929,8 +2929,13 @@ public static void NoBackwardTimeZones() foreach (TimeZoneInfo timezone in tzCollection) { + Console.WriteLine($"tzCollection: {timezone.DisplayName}"); tzDisplayNames.Add(timezone.DisplayName); } + foreach (string timezone in tzDisplayNames) + { + Console.WriteLine($"tzDisplayNames: {timezone}"); + } Assert.Equal(tzCollection.Count, tzDisplayNames.Count); } From 9da475416da684e108b3b6bbf125f2db9b207ad1 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Fri, 21 Jan 2022 11:04:27 -0500 Subject: [PATCH 08/13] Figure out backwards IDs on linux and maybe windows --- src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index aa35f2cc14094e..9da7922c9d4fb4 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -2929,7 +2929,7 @@ public static void NoBackwardTimeZones() foreach (TimeZoneInfo timezone in tzCollection) { - Console.WriteLine($"tzCollection: {timezone.DisplayName}"); + Console.WriteLine($"tzCollection: id {timezone.Id} has DisplayName {timezone.DisplayName}"); tzDisplayNames.Add(timezone.DisplayName); } foreach (string timezone in tzDisplayNames) From 2a96703fa869135e8153d97a317f04b7704e0aea Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Fri, 21 Jan 2022 14:54:54 -0500 Subject: [PATCH 09/13] [libraries] ActiveIssue NoBackwardTimeZones for Linux Arm64 --- src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 9da7922c9d4fb4..569e02f90ad5e8 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -2922,6 +2922,7 @@ public static void AdjustmentRuleBaseUtcOffsetDeltaTest() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64111", typeof(PlatformDetection), nameof(PlatformDetection.IsLinux), nameof(PlatformDetection.IsArm64Process))] public static void NoBackwardTimeZones() { ReadOnlyCollection tzCollection = TimeZoneInfo.GetSystemTimeZones(); From 559df412ebc8d28f5e4af66f49efe6e474cb4910 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Fri, 21 Jan 2022 15:21:43 -0500 Subject: [PATCH 10/13] Cleanup --- .../src/System/TimeZoneInfo.Unix.Android.cs | 2 +- .../System.Runtime/tests/System/TimeZoneInfoTests.cs | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs index bbeee7ebbd4631..64369e405b35d8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs @@ -311,7 +311,7 @@ private bool LoadData(string tzFileDir, string path) } return true; } - catch {} // TODO add warning + catch {} return false; } diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 569e02f90ad5e8..2cd4e8d84930d0 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -2930,13 +2930,8 @@ public static void NoBackwardTimeZones() foreach (TimeZoneInfo timezone in tzCollection) { - Console.WriteLine($"tzCollection: id {timezone.Id} has DisplayName {timezone.DisplayName}"); tzDisplayNames.Add(timezone.DisplayName); } - foreach (string timezone in tzDisplayNames) - { - Console.WriteLine($"tzDisplayNames: {timezone}"); - } Assert.Equal(tzCollection.Count, tzDisplayNames.Count); } From 09e71d20c99f2acd3dfda22becc359f9691d5f83 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Fri, 21 Jan 2022 18:59:32 -0500 Subject: [PATCH 11/13] Skip test with TestPlatforms instead --- src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 2cd4e8d84930d0..c9e3bdbaa9ea50 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -2922,7 +2922,7 @@ public static void AdjustmentRuleBaseUtcOffsetDeltaTest() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/64111", typeof(PlatformDetection), nameof(PlatformDetection.IsLinux), nameof(PlatformDetection.IsArm64Process))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64111", TestPlatforms.Linux)] public static void NoBackwardTimeZones() { ReadOnlyCollection tzCollection = TimeZoneInfo.GetSystemTimeZones(); From b3b4845d6164d2fff4e086d0c9e4317e97db376d Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Mon, 24 Jan 2022 11:14:47 -0500 Subject: [PATCH 12/13] Optimize further by not allocating a list for GetTimeZoneIDs --- .../src/System/TimeZoneInfo.Unix.Android.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs index 64369e405b35d8..616e6ecf513a5d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs @@ -428,15 +428,23 @@ private void LoadEntryAt(Stream fs, long position, out string id, out int byteOf public string[] GetTimeZoneIds() { - List nonBackwardsTZIDs = new List(); + int numTimeZoneIDs = 0; for (int i = 0; i < _ids.Length; i++) { if (!_isBackwards[i]) { - nonBackwardsTZIDs.Add(_ids[i]); + numTimeZoneIDs++; } } - return nonBackwardsTZIDs.ToArray(); + string[] nonBackwardsTZIDs = new string[numTimeZoneIDs]; + for (int i = 0; i < _ids.Length; i++) + { + if (!_isBackwards[i]) + { + nonBackwardsTZIDs[i] = _ids[i]; + } + } + return nonBackwardsTZIDs; } public string GetTimeZoneDirectory() From a65bc46dc6c13ddea1121b271e86eb07762c155a Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Mon, 24 Jan 2022 13:55:28 -0500 Subject: [PATCH 13/13] Fix indexing --- .../src/System/TimeZoneInfo.Unix.Android.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs index 616e6ecf513a5d..23c1044e1983cd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs @@ -437,11 +437,13 @@ public string[] GetTimeZoneIds() } } string[] nonBackwardsTZIDs = new string[numTimeZoneIDs]; + var index = 0; for (int i = 0; i < _ids.Length; i++) { if (!_isBackwards[i]) { - nonBackwardsTZIDs[i] = _ids[i]; + nonBackwardsTZIDs[index] = _ids[i]; + index++; } } return nonBackwardsTZIDs;