diff options
author | Krzysztof Wicher <mordotymoja@gmail.com> | 2018-07-12 20:24:07 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-12 20:24:07 -0700 |
commit | c1c7291b6f40e16f34202ad0d04d491f47523f42 (patch) | |
tree | 157377572158e491c4dd4d278209b580e7c4c3d9 | |
parent | f738f1ba914f535dba9e9f75b35c50d477fcecca (diff) | |
download | coreclr-c1c7291b6f40e16f34202ad0d04d491f47523f42.tar.gz coreclr-c1c7291b6f40e16f34202ad0d04d491f47523f42.tar.bz2 coreclr-c1c7291b6f40e16f34202ad0d04d491f47523f42.zip |
Skip old time zones adjustments with offsets higher than 14h (#18305) (#18874)
* Skip old time zones with offsets higher than 14h
* apply offline feedback
* fix braces
-rw-r--r-- | src/mscorlib/shared/System/TimeZoneInfo.Unix.cs | 28 | ||||
-rw-r--r-- | src/mscorlib/shared/System/TimeZoneInfo.cs | 89 |
2 files changed, 104 insertions, 13 deletions
diff --git a/src/mscorlib/shared/System/TimeZoneInfo.Unix.cs b/src/mscorlib/shared/System/TimeZoneInfo.Unix.cs index cc386a111f..2be5002844 100644 --- a/src/mscorlib/shared/System/TimeZoneInfo.Unix.cs +++ b/src/mscorlib/shared/System/TimeZoneInfo.Unix.cs @@ -595,6 +595,7 @@ namespace System } catch (ArgumentException) { } catch (InvalidTimeZoneException) { } + try { return new TimeZoneInfo(rawData, id, dstDisabled: true); // create a TimeZoneInfo instance from the TZif data w/o DST support @@ -602,7 +603,6 @@ namespace System catch (ArgumentException) { } catch (InvalidTimeZoneException) { } } - return null; } @@ -866,7 +866,7 @@ namespace System index++; } - if (index == 0) + if (rulesList.Count == 0 && index < dts.Length) { TZifType transitionType = TZif_GetEarlyDateTransitionType(transitionTypes); DateTime endTransitionDate = dts[index]; @@ -883,6 +883,12 @@ namespace System default(TransitionTime), baseUtcDelta, noDaylightTransitions: true); + + if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r)) + { + NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r); + } + rulesList.Add(r); } else if (index < dts.Length) @@ -920,6 +926,12 @@ namespace System default(TransitionTime), baseUtcDelta, noDaylightTransitions: true); + + if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r)) + { + NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r); + } + rulesList.Add(r); } else @@ -932,8 +944,14 @@ namespace System if (!string.IsNullOrEmpty(futureTransitionsPosixFormat)) { AdjustmentRule r = TZif_CreateAdjustmentRuleForPosixFormat(futureTransitionsPosixFormat, startTransitionDate, timeZoneBaseUtcOffset); + if (r != null) { + if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r)) + { + NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r); + } + rulesList.Add(r); } } @@ -954,6 +972,12 @@ namespace System default(TransitionTime), baseUtcDelta, noDaylightTransitions: true); + + if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r)) + { + NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r); + } + rulesList.Add(r); } } diff --git a/src/mscorlib/shared/System/TimeZoneInfo.cs b/src/mscorlib/shared/System/TimeZoneInfo.cs index 6e27376b68..e95321df26 100644 --- a/src/mscorlib/shared/System/TimeZoneInfo.cs +++ b/src/mscorlib/shared/System/TimeZoneInfo.cs @@ -1918,12 +1918,6 @@ namespace System } /// <summary> - /// Helper function that validates the TimeSpan is within +/- 14.0 hours - /// </summary> - internal static bool UtcOffsetOutOfRange(TimeSpan offset) => - offset.TotalHours < -14.0 || offset.TotalHours > 14.0; - - /// <summary> /// Helper function that performs all of the validation checks for the /// factory methods and deserialization callback. /// </summary> @@ -1972,11 +1966,7 @@ namespace System throw new InvalidTimeZoneException(SR.Argument_AdjustmentRulesNoNulls); } - // FUTURE: check to see if this rule supports Daylight Saving Time - // adjustmentRulesSupportDst = adjustmentRulesSupportDst || current.SupportsDaylightSavingTime; - // FUTURE: test baseUtcOffset + current.StandardDelta - - if (UtcOffsetOutOfRange(baseUtcOffset + current.DaylightDelta)) + if (!IsValidAdjustmentRuleOffest(baseUtcOffset, current)) { throw new InvalidTimeZoneException(SR.ArgumentOutOfRange_UtcOffsetAndDaylightDelta); } @@ -1989,5 +1979,82 @@ namespace System } } } + + private static readonly TimeSpan MaxOffset = TimeSpan.FromHours(14.0); + private static readonly TimeSpan MinOffset = -MaxOffset; + + /// <summary> + /// Helper function that validates the TimeSpan is within +/- 14.0 hours + /// </summary> + internal static bool UtcOffsetOutOfRange(TimeSpan offset) => + offset < MinOffset || offset > MaxOffset; + + private static TimeSpan GetUtcOffset(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule) + { + return baseUtcOffset + + adjustmentRule.BaseUtcOffsetDelta + + (adjustmentRule.HasDaylightSaving ? adjustmentRule.DaylightDelta : TimeSpan.Zero); + } + + /// <summary> + /// Helper function that performs adjustment rule validation + /// </summary> + private static bool IsValidAdjustmentRuleOffest(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule) + { + TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule); + return !UtcOffsetOutOfRange(utcOffset); + } + + /// <summary> + /// Normalize adjustment rule offset so that it is within valid range + /// This method should not be called at all but is here in case something changes in the future + /// or if really old time zones are present on the OS (no combination is known at the moment) + /// </summary> + private static void NormalizeAdjustmentRuleOffset(TimeSpan baseUtcOffset, ref AdjustmentRule adjustmentRule) + { + // Certain time zones such as: + // Time Zone start date end date offset + // ----------------------------------------------------- + // America/Yakutat 0001-01-01 1867-10-18 14:41:00 + // America/Yakutat 1867-10-18 1900-08-20 14:41:00 + // America/Sitka 0001-01-01 1867-10-18 14:58:00 + // America/Sitka 1867-10-18 1900-08-20 14:58:00 + // Asia/Manila 0001-01-01 1844-12-31 -15:56:00 + // Pacific/Guam 0001-01-01 1845-01-01 -14:21:00 + // Pacific/Saipan 0001-01-01 1845-01-01 -14:21:00 + // + // have larger offset than currently supported by framework. + // If for whatever reason we find that time zone exceeding max + // offset of 14h this function will truncate it to the max valid offset. + // Updating max offset may cause problems with interacting with SQL server + // which uses SQL DATETIMEOFFSET field type which was originally designed to be + // bit-for-bit compatible with DateTimeOffset. + + TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule); + + // utc base offset delta increment + TimeSpan adjustment = TimeSpan.Zero; + + if (utcOffset > MaxOffset) + { + adjustment = MaxOffset - utcOffset; + } + else if (utcOffset < MinOffset) + { + adjustment = MinOffset - utcOffset; + } + + if (adjustment != TimeSpan.Zero) + { + adjustmentRule = AdjustmentRule.CreateAdjustmentRule( + adjustmentRule.DateStart, + adjustmentRule.DateEnd, + adjustmentRule.DaylightDelta, + adjustmentRule.DaylightTransitionStart, + adjustmentRule.DaylightTransitionEnd, + adjustmentRule.BaseUtcOffsetDelta + adjustment, + adjustmentRule.NoDaylightTransitions); + } + } } } |