diff options
Diffstat (limited to 'src/mscorlib/shared/System/TimeZoneInfo.cs')
-rw-r--r-- | src/mscorlib/shared/System/TimeZoneInfo.cs | 89 |
1 files changed, 78 insertions, 11 deletions
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); + } + } } } |