diff options
author | Miguel de Icaza <miguel@gnome.org> | 2015-10-14 06:03:43 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2016-05-03 01:10:27 +0300 |
commit | 5f82524097130bf3e29844adcb47d1695bb14c6b (patch) | |
tree | b27b022f5c8c7e83039f383cfd2120f70248caaf /mcs/class/referencesource/mscorlib/system | |
parent | 2c381b5a7f699f4a0f3839bdb61ee79aca374376 (diff) |
DateTime, DateTimeOffset, bring Unix time APIs from CoreCLR
Diffstat (limited to 'mcs/class/referencesource/mscorlib/system')
-rw-r--r-- | mcs/class/referencesource/mscorlib/system/datetime.cs | 3 | ||||
-rw-r--r-- | mcs/class/referencesource/mscorlib/system/datetimeoffset.cs | 75 |
2 files changed, 68 insertions, 10 deletions
diff --git a/mcs/class/referencesource/mscorlib/system/datetime.cs b/mcs/class/referencesource/mscorlib/system/datetime.cs index 216fe8d12a6..930ed91fd50 100644 --- a/mcs/class/referencesource/mscorlib/system/datetime.cs +++ b/mcs/class/referencesource/mscorlib/system/datetime.cs @@ -82,6 +82,9 @@ namespace System { private const int DaysTo1601 = DaysPer400Years * 4; // 584388 // Number of days from 1/1/0001 to 12/30/1899 private const int DaysTo1899 = DaysPer400Years * 4 + DaysPer100Years * 3 - 367; + // Number of days from 1/1/0001 to 12/31/1969 + internal const int DaysTo1970 = DaysPer400Years * 4 + DaysPer100Years * 3 + DaysPer4Years * 17 + DaysPerYear; // 719,162 + // Number of days from 1/1/0001 to 12/31/9999 private const int DaysTo10000 = DaysPer400Years * 25 - 366; // 3652059 diff --git a/mcs/class/referencesource/mscorlib/system/datetimeoffset.cs b/mcs/class/referencesource/mscorlib/system/datetimeoffset.cs index 8f0aa8715bf..7f0348a838f 100644 --- a/mcs/class/referencesource/mscorlib/system/datetimeoffset.cs +++ b/mcs/class/referencesource/mscorlib/system/datetimeoffset.cs @@ -1,8 +1,6 @@ -// ==++== -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// ==--== +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + namespace System { using System; @@ -41,7 +39,14 @@ namespace System { // Constants internal const Int64 MaxOffset = TimeSpan.TicksPerHour * 14; internal const Int64 MinOffset = -MaxOffset; - + + 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); @@ -60,8 +65,8 @@ namespace System { m_dateTime = ValidateDate(dateTime, offset); } - // Constructs a DateTimeOffset from a DateTime. For UTC and Unspecified kinds, creates a - // UTC instance with a zero offset. For local, extracts the local offset. + // Constructs a DateTimeOffset from a DateTime. For Local and Unspecified kinds, + // extracts the local offset. For UTC, creates a UTC instance with a zero offset. public DateTimeOffset(DateTime dateTime) { TimeSpan offset; if (dateTime.Kind != DateTimeKind.Utc) { @@ -470,8 +475,30 @@ namespace System { public static DateTimeOffset FromFileTime(long fileTime) { return new DateTimeOffset(DateTime.FromFileTime(fileTime)); } - + public static DateTimeOffset FromUnixTimeSeconds(long seconds) { + if (seconds < UnixMinSeconds || seconds > UnixMaxSeconds) { + throw new ArgumentOutOfRangeException("seconds", + string.Format(Environment.GetResourceString("ArgumentOutOfRange_Range"), UnixMinSeconds, UnixMaxSeconds)); + } + + long ticks = seconds * TimeSpan.TicksPerSecond + UnixEpochTicks; + return new DateTimeOffset(ticks, TimeSpan.Zero); + } + + public static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds) { + const long MinMilliseconds = DateTime.MinTicks / TimeSpan.TicksPerMillisecond - UnixEpochMilliseconds; + const long MaxMilliseconds = DateTime.MaxTicks / TimeSpan.TicksPerMillisecond - UnixEpochMilliseconds; + + if (milliseconds < MinMilliseconds || milliseconds > MaxMilliseconds) { + throw new ArgumentOutOfRangeException("milliseconds", + string.Format(Environment.GetResourceString("ArgumentOutOfRange_Range"), MinMilliseconds, MaxMilliseconds)); + } + + long ticks = milliseconds * TimeSpan.TicksPerMillisecond + UnixEpochTicks; + return new DateTimeOffset(ticks, TimeSpan.Zero); + } + // ----- SECTION: private serialization instance methods ----------------* #if FEATURE_SERIALIZATION @@ -592,6 +619,34 @@ namespace System { public long ToFileTime() { return UtcDateTime.ToFileTime(); } + + public long ToUnixTimeSeconds() { + // Truncate sub-second precision before offsetting by the Unix Epoch to avoid + // the last digit being off by one for dates that result in negative Unix times. + // + // For example, consider the DateTimeOffset 12/31/1969 12:59:59.001 +0 + // ticks = 621355967990010000 + // ticksFromEpoch = ticks - UnixEpochTicks = -9990000 + // secondsFromEpoch = ticksFromEpoch / TimeSpan.TicksPerSecond = 0 + // + // Notice that secondsFromEpoch is rounded *up* by the truncation induced by integer division, + // whereas we actually always want to round *down* when converting to Unix time. This happens + // automatically for positive Unix time values. Now the example becomes: + // seconds = ticks / TimeSpan.TicksPerSecond = 62135596799 + // secondsFromEpoch = seconds - UnixEpochSeconds = -1 + // + // In other words, we want to consistently round toward the time 1/1/0001 00:00:00, + // rather than toward the Unix Epoch (1/1/1970 00:00:00). + long seconds = UtcDateTime.Ticks / TimeSpan.TicksPerSecond; + return seconds - UnixEpochSeconds; + } + + public long ToUnixTimeMilliseconds() { + // Truncate sub-millisecond precision before offsetting by the Unix Epoch to avoid + // the last digit being off by one for dates that result in negative Unix times + long milliseconds = UtcDateTime.Ticks / TimeSpan.TicksPerMillisecond; + return milliseconds - UnixEpochMilliseconds; + } public DateTimeOffset ToLocalTime() { return ToLocalTime(false); @@ -721,7 +776,7 @@ namespace System { } Contract.EndContractBlock(); - // RoundtripKind does not make sense for DateTimeOffset; ignore this flag for backward compatability with DateTime + // RoundtripKind does not make sense for DateTimeOffset; ignore this flag for backward compatibility with DateTime style &= ~DateTimeStyles.RoundtripKind; // AssumeLocal is also ignored as that is what we do by default with DateTimeOffset.Parse |