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