summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEric Erhardt <eric.erhardt@microsoft.com>2016-01-25 14:45:16 -0600
committerEric Erhardt <eric.erhardt@microsoft.com>2016-01-25 14:45:16 -0600
commit5c715f5e5603069745a74f831711d2fb3fb5933e (patch)
treed46be2d76bf7a4d95cad53ac2abb14ff99ed8432 /src
parent77446bd601dc1fe7f3d7e927b2c6cd312acfd3f4 (diff)
downloadcoreclr-5c715f5e5603069745a74f831711d2fb3fb5933e.tar.gz
coreclr-5c715f5e5603069745a74f831711d2fb3fb5933e.tar.bz2
coreclr-5c715f5e5603069745a74f831711d2fb3fb5933e.zip
TimeZoneInfo behaves differently before and after calling GetSystemTimeZones on Unix
Once GetSystemTimeZones() is called, TimeZoneInfo assumes it has all of the time zones from the local machine, and doesn't try going back to the local machine in FindSystemTimeZoneById. On Unix, we get all system time zones from the zones.tab file and each individual time zone comes from a tzfile with the "ID" as the file name. There are some tzfiles that aren't in the zones.tab file. This means if you call FindSystemTimeZoneById before calling GetSystemTimeZones(), it will be successful since we check the file system. But after you call GetSystemTimeZones(), a TimeZoneNotFoundException is thrown. In order to solve this, on Unix we always check the local machine for FindSystemTimeZoneById before throwing a TimeZoneNotFoundException, no matter if GetSystemTimeZones() was called already or not. Fix https://github.com/dotnet/corefx/issues/5469
Diffstat (limited to 'src')
-rw-r--r--src/mscorlib/src/System/TimeZoneInfo.cs61
1 files changed, 43 insertions, 18 deletions
diff --git a/src/mscorlib/src/System/TimeZoneInfo.cs b/src/mscorlib/src/System/TimeZoneInfo.cs
index c4548f3747..26cdfe16d9 100644
--- a/src/mscorlib/src/System/TimeZoneInfo.cs
+++ b/src/mscorlib/src/System/TimeZoneInfo.cs
@@ -3471,33 +3471,58 @@ namespace System {
// fall back to reading from the local machine
// when the cache is not fully populated
if (!cachedData.m_allSystemTimeZonesRead) {
+ result = TryGetTimeZoneFromLocalMachine(id, dstDisabled, out value, out e, cachedData);
+ }
+#if PLATFORM_UNIX
+ // On UNIX, there may be some tzfiles that aren't in the zones.tab file, and thus aren't returned from GetSystemTimeZones().
+ // If a caller asks for one of these zones before calling GetSystemTimeZones(), the time zone is returned successfully. But if
+ // GetSystemTimeZones() is called first, FindSystemTimeZoneById will throw TimeZoneNotFoundException, which is inconsistent.
+ // To fix this, even if m_allSystemTimeZonesRead is true, try reading the tzfile from disk, but don't add the time zone to the
+ // list returned from GetSystemTimeZones(). These time zones will only be available if asked for directly.
+ else {
+ result = TryGetTimeZoneFromLocalMachine(id, dstDisabled, out value, out e, cachedData);
+ }
+#else
+ else {
+ result = TimeZoneInfoResult.TimeZoneNotFoundException;
+ value = null;
+ }
+#endif // PLATFORM_UNIX
+
+ return result;
+ }
+
+ private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, bool dstDisabled, out TimeZoneInfo value, out Exception e, CachedData cachedData)
+ {
+ TimeZoneInfoResult result;
+ TimeZoneInfo match;
+
#if FEATURE_WIN32_REGISTRY
- result = TryGetTimeZoneByRegistryKey(id, out match, out e);
+ result = TryGetTimeZoneByRegistryKey(id, out match, out e);
#elif PLATFORM_UNIX
- result = TryGetTimeZoneByFile(id, out match, out e);
+ result = TryGetTimeZoneByFile(id, out match, out e);
#endif // FEATURE_WIN32_REGISTRY
- if (result == TimeZoneInfoResult.Success) {
- if (cachedData.m_systemTimeZones == null)
- cachedData.m_systemTimeZones = new Dictionary<string, TimeZoneInfo>();
+ if (result == TimeZoneInfoResult.Success)
+ {
+ if (cachedData.m_systemTimeZones == null)
+ cachedData.m_systemTimeZones = new Dictionary<string, TimeZoneInfo>();
- cachedData.m_systemTimeZones.Add(id, match);
+ cachedData.m_systemTimeZones.Add(id, match);
- if (dstDisabled && match.m_supportsDaylightSavingTime) {
- // we found a cache hit but we want a time zone without DST and this one has DST data
- value = CreateCustomTimeZone(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName);
- }
- else {
- value = new TimeZoneInfo(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName,
- match.m_daylightDisplayName, match.m_adjustmentRules, false);
- }
+ if (dstDisabled && match.m_supportsDaylightSavingTime)
+ {
+ // we found a cache hit but we want a time zone without DST and this one has DST data
+ value = CreateCustomTimeZone(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName);
}
- else {
- value = null;
+ else
+ {
+ value = new TimeZoneInfo(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName,
+ match.m_daylightDisplayName, match.m_adjustmentRules, false);
}
}
- else {
- result = TimeZoneInfoResult.TimeZoneNotFoundException;
+ else
+ {
value = null;
}