diff options
Diffstat (limited to 'src/mscorlib/src/System/TimeSpan.cs')
-rw-r--r-- | src/mscorlib/src/System/TimeSpan.cs | 302 |
1 files changed, 208 insertions, 94 deletions
diff --git a/src/mscorlib/src/System/TimeSpan.cs b/src/mscorlib/src/System/TimeSpan.cs index 7b71b48fed..9166656d0f 100644 --- a/src/mscorlib/src/System/TimeSpan.cs +++ b/src/mscorlib/src/System/TimeSpan.cs @@ -2,15 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System { - using System.Text; - using System; - using System.Runtime; - using System.Runtime.CompilerServices; - using System.Runtime.Versioning; - using System.Diagnostics.Contracts; - using System.Globalization; - +using System.Text; +using System; +using System.Runtime; +using System.Runtime.CompilerServices; +using System.Runtime.Versioning; +using System.Diagnostics.Contracts; +using System.Globalization; + +namespace System +{ // TimeSpan represents a duration of time. A TimeSpan can be negative // or positive. // @@ -28,14 +29,15 @@ namespace System { // details of this type should change, or new fields added, we need to remember to add // an appropriate custom ILMarshaler to keep WInRT interop scenarios enabled. // - [Serializable] public struct TimeSpan : IComparable + [Serializable] + public struct TimeSpan : IComparable , IComparable<TimeSpan>, IEquatable<TimeSpan>, IFormattable { - public const long TicksPerMillisecond = 10000; + public const long TicksPerMillisecond = 10000; private const double MillisecondsPerTick = 1.0 / TicksPerMillisecond; public const long TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000 - private const double SecondsPerTick = 1.0 / TicksPerSecond; // 0.0001 + private const double SecondsPerTick = 1.0 / TicksPerSecond; // 0.0001 public const long TicksPerMinute = TicksPerSecond * 60; // 600,000,000 private const double MinutesPerTick = 1.0 / TicksPerMinute; // 1.6666666666667e-9 @@ -72,16 +74,18 @@ namespace System { // _ticks = 0; //} - public TimeSpan(long ticks) { + public TimeSpan(long ticks) + { this._ticks = ticks; } - public TimeSpan(int hours, int minutes, int seconds) { + public TimeSpan(int hours, int minutes, int seconds) + { _ticks = TimeToTicks(hours, minutes, seconds); } public TimeSpan(int days, int hours, int minutes, int seconds) - : this(days,hours,minutes,seconds,0) + : this(days, hours, minutes, seconds, 0) { } @@ -89,44 +93,54 @@ namespace System { { Int64 totalMilliSeconds = ((Int64)days * 3600 * 24 + (Int64)hours * 3600 + (Int64)minutes * 60 + seconds) * 1000 + milliseconds; if (totalMilliSeconds > MaxMilliSeconds || totalMilliSeconds < MinMilliSeconds) - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("Overflow_TimeSpanTooLong")); - _ticks = (long)totalMilliSeconds * TicksPerMillisecond; + throw new ArgumentOutOfRangeException(null, SR.Overflow_TimeSpanTooLong); + _ticks = (long)totalMilliSeconds * TicksPerMillisecond; } - public long Ticks { + public long Ticks + { get { return _ticks; } } - public int Days { + public int Days + { get { return (int)(_ticks / TicksPerDay); } } - public int Hours { + public int Hours + { get { return (int)((_ticks / TicksPerHour) % 24); } } - public int Milliseconds { + public int Milliseconds + { get { return (int)((_ticks / TicksPerMillisecond) % 1000); } } - public int Minutes { + public int Minutes + { get { return (int)((_ticks / TicksPerMinute) % 60); } } - public int Seconds { + public int Seconds + { get { return (int)((_ticks / TicksPerSecond) % 60); } } - public double TotalDays { + public double TotalDays + { get { return ((double)_ticks) * DaysPerTick; } } - public double TotalHours { + public double TotalHours + { get { return (double)_ticks * HoursPerTick; } } - public double TotalMilliseconds { - get { + public double TotalMilliseconds + { + get + { double temp = (double)_ticks * MillisecondsPerTick; if (temp > MaxMilliSeconds) return (double)MaxMilliSeconds; @@ -138,21 +152,24 @@ namespace System { } } - public double TotalMinutes { + public double TotalMinutes + { get { return (double)_ticks * MinutesPerTick; } } - public double TotalSeconds { + public double TotalSeconds + { get { return (double)_ticks * SecondsPerTick; } } - public TimeSpan Add(TimeSpan ts) { + public TimeSpan Add(TimeSpan ts) + { long result = _ticks + ts._ticks; // Overflow if signs of operands was identical and result's // sign was opposite. // >> 63 gives the sign bit (either 64 1's or 64 0's). if ((_ticks >> 63 == ts._ticks >> 63) && (_ticks >> 63 != result >> 63)) - throw new OverflowException(Environment.GetResourceString("Overflow_TimeSpanTooLong")); + throw new OverflowException(SR.Overflow_TimeSpanTooLong); return new TimeSpan(result); } @@ -160,43 +177,50 @@ namespace System { // Compares two TimeSpan values, returning an integer that indicates their // relationship. // - public static int Compare(TimeSpan t1, TimeSpan t2) { + public static int Compare(TimeSpan t1, TimeSpan t2) + { if (t1._ticks > t2._ticks) return 1; if (t1._ticks < t2._ticks) return -1; return 0; } // Returns a value less than zero if this object - public int CompareTo(Object value) { + public int CompareTo(Object value) + { if (value == null) return 1; if (!(value is TimeSpan)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeTimeSpan")); + throw new ArgumentException(SR.Arg_MustBeTimeSpan); long t = ((TimeSpan)value)._ticks; if (_ticks > t) return 1; if (_ticks < t) return -1; return 0; } - public int CompareTo(TimeSpan value) { + public int CompareTo(TimeSpan value) + { long t = value._ticks; if (_ticks > t) return 1; if (_ticks < t) return -1; return 0; } - public static TimeSpan FromDays(double value) { + public static TimeSpan FromDays(double value) + { return Interval(value, MillisPerDay); } - public TimeSpan Duration() { - if (Ticks==TimeSpan.MinValue.Ticks) - throw new OverflowException(Environment.GetResourceString("Overflow_Duration")); + public TimeSpan Duration() + { + if (Ticks == TimeSpan.MinValue.Ticks) + throw new OverflowException(SR.Overflow_Duration); Contract.EndContractBlock(); - return new TimeSpan(_ticks >= 0? _ticks: -_ticks); + return new TimeSpan(_ticks >= 0 ? _ticks : -_ticks); } - public override bool Equals(Object value) { - if (value is TimeSpan) { + public override bool Equals(Object value) + { + if (value is TimeSpan) + { return _ticks == ((TimeSpan)value)._ticks; } return false; @@ -207,169 +231,255 @@ namespace System { return _ticks == obj._ticks; } - public static bool Equals(TimeSpan t1, TimeSpan t2) { + public static bool Equals(TimeSpan t1, TimeSpan t2) + { return t1._ticks == t2._ticks; } - public override int GetHashCode() { + public override int GetHashCode() + { return (int)_ticks ^ (int)(_ticks >> 32); } - public static TimeSpan FromHours(double value) { + public static TimeSpan FromHours(double value) + { return Interval(value, MillisPerHour); } - private static TimeSpan Interval(double value, int scale) { + private static TimeSpan Interval(double value, int scale) + { if (Double.IsNaN(value)) - throw new ArgumentException(Environment.GetResourceString("Arg_CannotBeNaN")); + throw new ArgumentException(SR.Arg_CannotBeNaN); Contract.EndContractBlock(); double tmp = value * scale; - double millis = tmp + (value >= 0? 0.5: -0.5); + double millis = tmp + (value >= 0 ? 0.5 : -0.5); if ((millis > Int64.MaxValue / TicksPerMillisecond) || (millis < Int64.MinValue / TicksPerMillisecond)) - throw new OverflowException(Environment.GetResourceString("Overflow_TimeSpanTooLong")); + throw new OverflowException(SR.Overflow_TimeSpanTooLong); return new TimeSpan((long)millis * TicksPerMillisecond); } - public static TimeSpan FromMilliseconds(double value) { + public static TimeSpan FromMilliseconds(double value) + { return Interval(value, 1); } - public static TimeSpan FromMinutes(double value) { + public static TimeSpan FromMinutes(double value) + { return Interval(value, MillisPerMinute); } - public TimeSpan Negate() { - if (Ticks==TimeSpan.MinValue.Ticks) - throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum")); + public TimeSpan Negate() + { + if (Ticks == TimeSpan.MinValue.Ticks) + throw new OverflowException(SR.Overflow_NegateTwosCompNum); Contract.EndContractBlock(); return new TimeSpan(-_ticks); } - public static TimeSpan FromSeconds(double value) { + public static TimeSpan FromSeconds(double value) + { return Interval(value, MillisPerSecond); } - public TimeSpan Subtract(TimeSpan ts) { + public TimeSpan Subtract(TimeSpan ts) + { long result = _ticks - ts._ticks; // Overflow if signs of operands was different and result's // sign was opposite from the first argument's sign. // >> 63 gives the sign bit (either 64 1's or 64 0's). if ((_ticks >> 63 != ts._ticks >> 63) && (_ticks >> 63 != result >> 63)) - throw new OverflowException(Environment.GetResourceString("Overflow_TimeSpanTooLong")); + throw new OverflowException(SR.Overflow_TimeSpanTooLong); return new TimeSpan(result); } - public static TimeSpan FromTicks(long value) { + public TimeSpan Multiply(double factor) => this * factor; + + public TimeSpan Divide(double divisor) => this / divisor; + + public double Divide(TimeSpan ts) => this / ts; + + public static TimeSpan FromTicks(long value) + { return new TimeSpan(value); } - internal static long TimeToTicks(int hour, int minute, int second) { + internal static long TimeToTicks(int hour, int minute, int second) + { // totalSeconds is bounded by 2^31 * 2^12 + 2^31 * 2^8 + 2^31, // which is less than 2^44, meaning we won't overflow totalSeconds. long totalSeconds = (long)hour * 3600 + (long)minute * 60 + (long)second; if (totalSeconds > MaxSeconds || totalSeconds < MinSeconds) - throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("Overflow_TimeSpanTooLong")); + throw new ArgumentOutOfRangeException(null, SR.Overflow_TimeSpanTooLong); return totalSeconds * TicksPerSecond; } // See System.Globalization.TimeSpanParse and System.Globalization.TimeSpanFormat #region ParseAndFormat - public static TimeSpan Parse(String s) { + public static TimeSpan Parse(String s) + { /* Constructs a TimeSpan from a string. Leading and trailing white space characters are allowed. */ return TimeSpanParse.Parse(s, null); } - public static TimeSpan Parse(String input, IFormatProvider formatProvider) { + public static TimeSpan Parse(String input, IFormatProvider formatProvider) + { return TimeSpanParse.Parse(input, formatProvider); } - public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider) { + public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider) + { return TimeSpanParse.ParseExact(input, format, formatProvider, TimeSpanStyles.None); } - public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider) { + public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider) + { return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None); } - public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles) { + public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles) + { TimeSpanParse.ValidateStyles(styles, nameof(styles)); return TimeSpanParse.ParseExact(input, format, formatProvider, styles); } - public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles) { + public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles) + { TimeSpanParse.ValidateStyles(styles, nameof(styles)); return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, styles); } - public static Boolean TryParse(String s, out TimeSpan result) { + public static Boolean TryParse(String s, out TimeSpan result) + { return TimeSpanParse.TryParse(s, null, out result); } - public static Boolean TryParse(String input, IFormatProvider formatProvider, out TimeSpan result) { + public static Boolean TryParse(String input, IFormatProvider formatProvider, out TimeSpan result) + { return TimeSpanParse.TryParse(input, formatProvider, out result); } - public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, out TimeSpan result) { + public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, out TimeSpan result) + { return TimeSpanParse.TryParseExact(input, format, formatProvider, TimeSpanStyles.None, out result); } - public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, out TimeSpan result) { + public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, out TimeSpan result) + { return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result); } - public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) { + public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) + { TimeSpanParse.ValidateStyles(styles, nameof(styles)); return TimeSpanParse.TryParseExact(input, format, formatProvider, styles, out result); } - public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) { + public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) + { TimeSpanParse.ValidateStyles(styles, nameof(styles)); return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result); } - public override String ToString() { + public override String ToString() + { return TimeSpanFormat.Format(this, null, null); } - public String ToString(String format) { + public String ToString(String format) + { return TimeSpanFormat.Format(this, format, null); } - public String ToString(String format, IFormatProvider formatProvider) { - if (LegacyMode) { + public String ToString(String format, IFormatProvider formatProvider) + { + if (LegacyMode) + { return TimeSpanFormat.Format(this, null, null); } - else { + else + { return TimeSpanFormat.Format(this, format, formatProvider); } } #endregion - - public static TimeSpan operator -(TimeSpan t) { - if (t._ticks==TimeSpan.MinValue._ticks) - throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum")); + + public static TimeSpan operator -(TimeSpan t) + { + if (t._ticks == TimeSpan.MinValue._ticks) + throw new OverflowException(SR.Overflow_NegateTwosCompNum); return new TimeSpan(-t._ticks); } - public static TimeSpan operator -(TimeSpan t1, TimeSpan t2) { + public static TimeSpan operator -(TimeSpan t1, TimeSpan t2) + { return t1.Subtract(t2); } - public static TimeSpan operator +(TimeSpan t) { + public static TimeSpan operator +(TimeSpan t) + { return t; } - public static TimeSpan operator +(TimeSpan t1, TimeSpan t2) { + public static TimeSpan operator +(TimeSpan t1, TimeSpan t2) + { return t1.Add(t2); } - public static bool operator ==(TimeSpan t1, TimeSpan t2) { + public static TimeSpan operator *(TimeSpan timeSpan, double factor) + { + if (double.IsNaN(factor)) + { + throw new ArgumentException(SR.Arg_CannotBeNaN, nameof(factor)); + } + + // Rounding to the nearest tick is as close to the result we would have with unlimited + // precision as possible, and so likely to have the least potential to surprise. + double ticks = Math.Round(timeSpan.Ticks * factor); + if (ticks > long.MaxValue | ticks < long.MinValue) + { + throw new OverflowException(SR.Overflow_TimeSpanTooLong); + } + + return FromTicks((long)ticks); + } + + public static TimeSpan operator *(double factor, TimeSpan timeSpan) => timeSpan * factor; + + public static TimeSpan operator /(TimeSpan timeSpan, double divisor) + { + if (double.IsNaN(divisor)) + { + throw new ArgumentException(SR.Arg_CannotBeNaN, nameof(divisor)); + } + + double ticks = Math.Round(timeSpan.Ticks / divisor); + if (ticks > long.MaxValue | ticks < long.MinValue || double.IsNaN(ticks)) + { + throw new OverflowException(SR.Overflow_TimeSpanTooLong); + } + + return FromTicks((long)ticks); + } + + // Using floating-point arithmetic directly means that infinities can be returned, which is reasonable + // if we consider TimeSpan.FromHours(1) / TimeSpan.Zero asks how many zero-second intervals there are in + // an hour for which ∞ is the mathematic correct answer. Having TimeSpan.Zero / TimeSpan.Zero return NaN + // is perhaps less useful, but no less useful than an exception. + public static double operator /(TimeSpan t1, TimeSpan t2) => t1.Ticks / (double)t2.Ticks; + + public static bool operator ==(TimeSpan t1, TimeSpan t2) + { return t1._ticks == t2._ticks; } - public static bool operator !=(TimeSpan t1, TimeSpan t2) { + public static bool operator !=(TimeSpan t1, TimeSpan t2) + { return t1._ticks != t2._ticks; } - public static bool operator <(TimeSpan t1, TimeSpan t2) { + public static bool operator <(TimeSpan t1, TimeSpan t2) + { return t1._ticks < t2._ticks; } - public static bool operator <=(TimeSpan t1, TimeSpan t2) { + public static bool operator <=(TimeSpan t1, TimeSpan t2) + { return t1._ticks <= t2._ticks; } - public static bool operator >(TimeSpan t1, TimeSpan t2) { + public static bool operator >(TimeSpan t1, TimeSpan t2) + { return t1._ticks > t2._ticks; } - public static bool operator >=(TimeSpan t1, TimeSpan t2) { + public static bool operator >=(TimeSpan t1, TimeSpan t2) + { return t1._ticks >= t2._ticks; } @@ -405,16 +515,20 @@ namespace System { // [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework] // "TimeSpan_LegacyFormatMode"=dword:00000001 // - private static bool GetLegacyFormatMode() { + private static bool GetLegacyFormatMode() + { return false; } private static volatile bool _legacyConfigChecked; private static volatile bool _legacyMode; - private static bool LegacyMode { - get { - if (!_legacyConfigChecked) { + private static bool LegacyMode + { + get + { + if (!_legacyConfigChecked) + { // no need to lock - idempotent _legacyMode = GetLegacyFormatMode(); _legacyConfigChecked = true; |