-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Android remove backward timezones #64028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
e08f971
7258e39
3c86169
9f6adce
602201f
86a56b8
ec59f25
9da4754
2a96703
559df41
09e71d2
b3b4845
a65bc46
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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,13 +235,94 @@ public AndroidTzData() | |
| { | ||
| _tzFileDir = tzFileDir; | ||
| _tzFilePath = tzFilePath; | ||
| _isFiltered = false; | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| 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: | ||
| // | ||
| // <timezones ianaversion="2019b"> | ||
| // <countryzones> | ||
| // <country code="au" default="Australia/Sydney" everutc="n"> | ||
| // <id alts="Australia/ACT,Australia/Canberra,Australia/NSW">Australia/Sydney</id> | ||
| // ... | ||
| // ... | ||
| // <id>Australia/Eucla</id> | ||
| // </country> | ||
| // <country ...> | ||
| // ... | ||
| // ... | ||
| // ... | ||
| // </country> | ||
| // </countryzones> | ||
| // </timezones> | ||
| // | ||
| // 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>(); | ||
| string? tzLookupLine; | ||
| while (sr.Peek() >= 0) | ||
| { | ||
| if (!(tzLookupLine = sr.ReadLine())!.TrimStart().StartsWith("<id")) | ||
mdh1418 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| continue; | ||
|
|
||
mdh1418 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| int idStart = tzLookupLine.IndexOf('>') + 1; | ||
| int idLength = tzLookupLine.LastIndexOf("</") - idStart; | ||
mdh1418 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (idStart == 0 || idLength < 0) | ||
mdh1418 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| // Either the start tag <id ... > or the end tag </id> are not found | ||
| continue; | ||
| } | ||
| string id = tzLookupLine.Substring(idStart, idLength); | ||
| tzLookupIDs.Add(id); | ||
| } | ||
| var cleanIDs = new List<string>(); | ||
| var cleanOffsets = new List<int>(); | ||
| var cleanLengths = new List<int>(); | ||
| 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) | ||
mdh1418 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| 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; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.