@@ -1917,12 +1917,6 @@ private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, bool
1917
1917
return result ;
1918
1918
}
1919
1919
1920
- /// <summary>
1921
- /// Helper function that validates the TimeSpan is within +/- 14.0 hours
1922
- /// </summary>
1923
- internal static bool UtcOffsetOutOfRange ( TimeSpan offset ) =>
1924
- offset . TotalHours < - 14.0 || offset . TotalHours > 14.0 ;
1925
-
1926
1920
/// <summary>
1927
1921
/// Helper function that performs all of the validation checks for the
1928
1922
/// factory methods and deserialization callback.
@@ -1972,11 +1966,7 @@ private static void ValidateTimeZoneInfo(string id, TimeSpan baseUtcOffset, Adju
1972
1966
throw new InvalidTimeZoneException ( SR . Argument_AdjustmentRulesNoNulls ) ;
1973
1967
}
1974
1968
1975
- // FUTURE: check to see if this rule supports Daylight Saving Time
1976
- // adjustmentRulesSupportDst = adjustmentRulesSupportDst || current.SupportsDaylightSavingTime;
1977
- // FUTURE: test baseUtcOffset + current.StandardDelta
1978
-
1979
- if ( UtcOffsetOutOfRange ( baseUtcOffset + current . DaylightDelta ) )
1969
+ if ( ! IsValidAdjustmentRuleOffest ( baseUtcOffset , current ) )
1980
1970
{
1981
1971
throw new InvalidTimeZoneException ( SR . ArgumentOutOfRange_UtcOffsetAndDaylightDelta ) ;
1982
1972
}
@@ -1989,5 +1979,82 @@ private static void ValidateTimeZoneInfo(string id, TimeSpan baseUtcOffset, Adju
1989
1979
}
1990
1980
}
1991
1981
}
1982
+
1983
+ private static readonly TimeSpan MaxOffset = TimeSpan . FromHours ( 14.0 ) ;
1984
+ private static readonly TimeSpan MinOffset = - MaxOffset ;
1985
+
1986
+ /// <summary>
1987
+ /// Helper function that validates the TimeSpan is within +/- 14.0 hours
1988
+ /// </summary>
1989
+ internal static bool UtcOffsetOutOfRange ( TimeSpan offset ) =>
1990
+ offset < MinOffset || offset > MaxOffset ;
1991
+
1992
+ private static TimeSpan GetUtcOffset ( TimeSpan baseUtcOffset , AdjustmentRule adjustmentRule )
1993
+ {
1994
+ return baseUtcOffset
1995
+ + adjustmentRule . BaseUtcOffsetDelta
1996
+ + ( adjustmentRule . HasDaylightSaving ? adjustmentRule . DaylightDelta : TimeSpan . Zero ) ;
1997
+ }
1998
+
1999
+ /// <summary>
2000
+ /// Helper function that performs adjustment rule validation
2001
+ /// </summary>
2002
+ private static bool IsValidAdjustmentRuleOffest ( TimeSpan baseUtcOffset , AdjustmentRule adjustmentRule )
2003
+ {
2004
+ TimeSpan utcOffset = GetUtcOffset ( baseUtcOffset , adjustmentRule ) ;
2005
+ return ! UtcOffsetOutOfRange ( utcOffset ) ;
2006
+ }
2007
+
2008
+ /// <summary>
2009
+ /// Normalize adjustment rule offset so that it is within valid range
2010
+ /// This method should not be called at all but is here in case something changes in the future
2011
+ /// or if really old time zones are present on the OS (no combination is known at the moment)
2012
+ /// </summary>
2013
+ private static void NormalizeAdjustmentRuleOffset ( TimeSpan baseUtcOffset , ref AdjustmentRule adjustmentRule )
2014
+ {
2015
+ // Certain time zones such as:
2016
+ // Time Zone start date end date offset
2017
+ // -----------------------------------------------------
2018
+ // America/Yakutat 0001-01-01 1867-10-18 14:41:00
2019
+ // America/Yakutat 1867-10-18 1900-08-20 14:41:00
2020
+ // America/Sitka 0001-01-01 1867-10-18 14:58:00
2021
+ // America/Sitka 1867-10-18 1900-08-20 14:58:00
2022
+ // Asia/Manila 0001-01-01 1844-12-31 -15:56:00
2023
+ // Pacific/Guam 0001-01-01 1845-01-01 -14:21:00
2024
+ // Pacific/Saipan 0001-01-01 1845-01-01 -14:21:00
2025
+ //
2026
+ // have larger offset than currently supported by framework.
2027
+ // If for whatever reason we find that time zone exceeding max
2028
+ // offset of 14h this function will truncate it to the max valid offset.
2029
+ // Updating max offset may cause problems with interacting with SQL server
2030
+ // which uses SQL DATETIMEOFFSET field type which was originally designed to be
2031
+ // bit-for-bit compatible with DateTimeOffset.
2032
+
2033
+ TimeSpan utcOffset = GetUtcOffset ( baseUtcOffset , adjustmentRule ) ;
2034
+
2035
+ // utc base offset delta increment
2036
+ TimeSpan adjustment = TimeSpan . Zero ;
2037
+
2038
+ if ( utcOffset > MaxOffset )
2039
+ {
2040
+ adjustment = MaxOffset - utcOffset ;
2041
+ }
2042
+ else if ( utcOffset < MinOffset )
2043
+ {
2044
+ adjustment = MinOffset - utcOffset ;
2045
+ }
2046
+
2047
+ if ( adjustment != TimeSpan . Zero )
2048
+ {
2049
+ adjustmentRule = AdjustmentRule . CreateAdjustmentRule (
2050
+ adjustmentRule . DateStart ,
2051
+ adjustmentRule . DateEnd ,
2052
+ adjustmentRule . DaylightDelta ,
2053
+ adjustmentRule . DaylightTransitionStart ,
2054
+ adjustmentRule . DaylightTransitionEnd ,
2055
+ adjustmentRule . BaseUtcOffsetDelta + adjustment ,
2056
+ adjustmentRule . NoDaylightTransitions ) ;
2057
+ }
2058
+ }
1992
2059
}
1993
2060
}
0 commit comments