summaryrefslogtreecommitdiff
path: root/src/mscorlib/shared/System/TimeZoneInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/shared/System/TimeZoneInfo.cs')
-rw-r--r--src/mscorlib/shared/System/TimeZoneInfo.cs89
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);
+ }
+ }
}
}