diff options
author | Eric Erhardt <eric.erhardt@microsoft.com> | 2016-01-25 14:45:16 -0600 |
---|---|---|
committer | Eric Erhardt <eric.erhardt@microsoft.com> | 2016-01-25 14:45:16 -0600 |
commit | 5c715f5e5603069745a74f831711d2fb3fb5933e (patch) | |
tree | d46be2d76bf7a4d95cad53ac2abb14ff99ed8432 /src | |
parent | 77446bd601dc1fe7f3d7e927b2c6cd312acfd3f4 (diff) | |
download | coreclr-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.cs | 61 |
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; } |