summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/TimeSpan.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/TimeSpan.cs')
-rw-r--r--src/mscorlib/src/System/TimeSpan.cs302
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;