diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs b/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs index 861a8b8eac0836..624651c79c8219 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs @@ -291,18 +291,18 @@ public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds) /// public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds, int microseconds) { - long totalMicroseconds = (days * MicrosecondsPerDay) - + (hours * MicrosecondsPerHour) - + (minutes * MicrosecondsPerMinute) - + (seconds * MicrosecondsPerSecond) - + (milliseconds * MicrosecondsPerMillisecond) - + microseconds; + Int128 totalMicroseconds = Math.BigMul(days, MicrosecondsPerDay) + + Math.BigMul(hours, MicrosecondsPerHour) + + Math.BigMul(minutes, MicrosecondsPerMinute) + + Math.BigMul(seconds, MicrosecondsPerSecond) + + Math.BigMul(milliseconds, MicrosecondsPerMillisecond) + + microseconds; if ((totalMicroseconds > MaxMicroseconds) || (totalMicroseconds < MinMicroseconds)) { ThrowHelper.ThrowArgumentOutOfRange_TimeSpanTooLong(); } - _ticks = totalMicroseconds * TicksPerMicrosecond; + _ticks = (long)totalMicroseconds * TicksPerMicrosecond; } public long Ticks => _ticks; diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/TimeSpanTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/TimeSpanTests.cs index 4b619a1f48e80f..e66e910f38cabc 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/TimeSpanTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/TimeSpanTests.cs @@ -111,6 +111,32 @@ public static void Ctor_Int_Int_Int_Int_Int_Int_Invalid() AssertExtensions.Throws(null, () => new TimeSpan(max.Days, max.Hours, max.Minutes, max.Seconds, max.Milliseconds, max.Microseconds + 1)); } + [Theory] + [InlineData(4, 213_503_983, 0, 0, 0, 0, 0)] + [InlineData(4, -213_503_983, 0, 0, 0, 0, 0)] + [InlineData(6, 213_503_982, 8, 1, 49, 551, 616)] + [InlineData(5, 213_503_983, 0, 0, 0, 0, 0)] + [InlineData(6, 213_503_983, 0, 0, 0, 0, 0)] + public static void Ctor_DayBased_Overflow_Invalid(int argumentCount, int days, int hours, int minutes, int seconds, int milliseconds, int microseconds) + { + Action action = argumentCount switch + { + 4 => () => new TimeSpan(days, hours, minutes, seconds), + 5 => () => new TimeSpan(days, hours, minutes, seconds, milliseconds), + 6 => () => new TimeSpan(days, hours, minutes, seconds, milliseconds, microseconds), + _ => throw new ArgumentOutOfRangeException(nameof(argumentCount)), + }; + + AssertExtensions.Throws(null, action); + } + + [Fact] + public static void Ctor_DayBased_Boundary_Valid() + { + Assert.Equal(TimeSpan.FromDays(TimeSpan.MaxValue.Days), new TimeSpan(TimeSpan.MaxValue.Days, 0, 0, 0)); + Assert.Equal(TimeSpan.FromDays(TimeSpan.MinValue.Days), new TimeSpan(TimeSpan.MinValue.Days, 0, 0, 0)); + } + [Theory] [InlineData(100)] [InlineData(300)]