summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Erhardt <eric.erhardt@microsoft.com>2015-08-18 15:46:55 -0700
committerEric Erhardt <eric.erhardt@microsoft.com>2015-08-18 15:46:55 -0700
commit50ef79d48df81635e58ca59386620f0151df6022 (patch)
treefca7dd51b759e7c224c1af844417309a11dff2cd
parent8c369709553fc621156e0279bf96b91b2081f442 (diff)
parentdd57af2f2711a4acbdf11be2e29cfd5c2f077cc1 (diff)
downloadcoreclr-50ef79d48df81635e58ca59386620f0151df6022.tar.gz
coreclr-50ef79d48df81635e58ca59386620f0151df6022.tar.bz2
coreclr-50ef79d48df81635e58ca59386620f0151df6022.zip
Merge pull request #1397 from eerhardt/master
Handle newer tzfiles by allowing for the "big bang" transition.
-rw-r--r--src/mscorlib/src/System/DateTimeOffset.cs12
-rw-r--r--src/mscorlib/src/System/TimeZoneInfo.cs33
2 files changed, 36 insertions, 9 deletions
diff --git a/src/mscorlib/src/System/DateTimeOffset.cs b/src/mscorlib/src/System/DateTimeOffset.cs
index 7db5c4ca8e..7f0348a838 100644
--- a/src/mscorlib/src/System/DateTimeOffset.cs
+++ b/src/mscorlib/src/System/DateTimeOffset.cs
@@ -43,7 +43,10 @@ namespace System {
private const long UnixEpochTicks = TimeSpan.TicksPerDay * DateTime.DaysTo1970; // 621,355,968,000,000,000
private const long UnixEpochSeconds = UnixEpochTicks / TimeSpan.TicksPerSecond; // 62,135,596,800
private const long UnixEpochMilliseconds = UnixEpochTicks / TimeSpan.TicksPerMillisecond; // 62,135,596,800,000
-
+
+ internal const long UnixMinSeconds = DateTime.MinTicks / TimeSpan.TicksPerSecond - UnixEpochSeconds;
+ internal const long UnixMaxSeconds = DateTime.MaxTicks / TimeSpan.TicksPerSecond - UnixEpochSeconds;
+
// Static Fields
public static readonly DateTimeOffset MinValue = new DateTimeOffset(DateTime.MinTicks, TimeSpan.Zero);
public static readonly DateTimeOffset MaxValue = new DateTimeOffset(DateTime.MaxTicks, TimeSpan.Zero);
@@ -474,12 +477,9 @@ namespace System {
}
public static DateTimeOffset FromUnixTimeSeconds(long seconds) {
- const long MinSeconds = DateTime.MinTicks / TimeSpan.TicksPerSecond - UnixEpochSeconds;
- const long MaxSeconds = DateTime.MaxTicks / TimeSpan.TicksPerSecond - UnixEpochSeconds;
-
- if (seconds < MinSeconds || seconds > MaxSeconds) {
+ if (seconds < UnixMinSeconds || seconds > UnixMaxSeconds) {
throw new ArgumentOutOfRangeException("seconds",
- string.Format(Environment.GetResourceString("ArgumentOutOfRange_Range"), MinSeconds, MaxSeconds));
+ string.Format(Environment.GetResourceString("ArgumentOutOfRange_Range"), UnixMinSeconds, UnixMaxSeconds));
}
long ticks = seconds * TimeSpan.TicksPerSecond + UnixEpochTicks;
diff --git a/src/mscorlib/src/System/TimeZoneInfo.cs b/src/mscorlib/src/System/TimeZoneInfo.cs
index 900b5d0af7..bc8d76ed82 100644
--- a/src/mscorlib/src/System/TimeZoneInfo.cs
+++ b/src/mscorlib/src/System/TimeZoneInfo.cs
@@ -3621,8 +3621,15 @@ namespace System {
Byte[] typeOfLocalTime, TZifType[] transitionTypes, Boolean[] StandardTime, Boolean[] GmtTime, string futureTransitionsPosixFormat)
{
// To generate AdjustmentRules, use the following approach:
- // 1. The first AdjustmentRule goes from DateTime.Min to the first transition and uses the first standard transitionType
- // (or the first transitionType if none of them are standard)
+ // The first AdjustmentRule will go from DateTime.MinValue to the first transition time greater than DateTime.MinValue.
+ // Each middle AdjustmentRule wil go from dts[index-1] to dts[index].
+ // The last AdjustmentRule will go from dts[dts.Length-1] to Datetime.MaxValue.
+
+ // 0. Skip any DateTime.MinValue transition times. In newer versions of the tzfile, there
+ // is a "big bang" transition time, which is before the year 0001. Since any times before year 0001
+ // cannot be represented by DateTime, there is no reason to make AdjustmentRules for these unrepresentable time periods.
+ // 1. If there are no DateTime.MinValue times, the first AdjustmentRule goes from DateTime.MinValue
+ // to the first transition and uses the first standard transitionType (or the first transitionType if none of them are standard)
// 2. Create an AdjustmentRule for each transition, i.e. from dts[index - 1] to dts[index].
// This rule uses the transitionType[index - 1] and the whole AdjustmentRule only describes a single offset - either
// all daylight savings, or all stanard time.
@@ -3630,6 +3637,11 @@ namespace System {
// a. a POSIX-style timezone description ("futureTransitionsPosixFormat"), if there is one or
// b. continue the last transition offset until DateTime.Max
+ while (index < dts.Length && dts[index] == DateTime.MinValue)
+ {
+ index++;
+ }
+
if (index == 0)
{
TZifType transitionType = TZif_GetEarlyDateTransitionType(transitionTypes);
@@ -4128,6 +4140,21 @@ namespace System {
}
}
+ private static DateTime TZif_UnixTimeToDateTime(long unixTime)
+ {
+ if (unixTime < DateTimeOffset.UnixMinSeconds)
+ {
+ return DateTime.MinValue;
+ }
+
+ if (unixTime > DateTimeOffset.UnixMaxSeconds)
+ {
+ return DateTime.MaxValue;
+ }
+
+ return DateTimeOffset.FromUnixTimeSeconds(unixTime).UtcDateTime;
+ }
+
static private void TZif_ParseRaw(Byte[] data, out TZifHead t, out DateTime[] dts, out Byte[] typeOfLocalTime, out TZifType[] transitionType,
out String zoneAbbreviations, out Boolean[] StandardTime, out Boolean[] GmtTime, out string futureTransitionsPosixFormat)
{
@@ -4170,7 +4197,7 @@ namespace System {
//
for (int i = 0; i < t.TimeCount; i++) {
long unixTime = TZif_ToUnixTime(data, index, t.Version);
- dts[i] = DateTimeOffset.FromUnixTimeSeconds(unixTime).UtcDateTime;
+ dts[i] = TZif_UnixTimeToDateTime(unixTime);
index += timeValuesLength;
}