diff --git a/src/Polyfill/TimeSpanPolyfill.cs b/src/Polyfill/TimeSpanPolyfill.cs
index a9f3909b..74ecebd9 100644
--- a/src/Polyfill/TimeSpanPolyfill.cs
+++ b/src/Polyfill/TimeSpanPolyfill.cs
@@ -54,6 +54,64 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
return new((long)ticks);
}
+ // The decimal accumulation above costs hundreds of nanoseconds. When every component is small
+ // enough that its own tick count is at most an eighth of long.MaxValue, the (at most six)
+ // components cannot overflow an Int64 between them, so the ticks can be summed directly and
+ // the result is always in range. Anything larger takes the decimal path, which decides
+ // whether the total overflows.
+ const long MaxFastPathTicks = long.MaxValue / 8;
+
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+
+ // Components an overload does not have arrive as zero; leave them out of the decimal sum
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+
+ return TicksFromMicroseconds(total);
+ }
+
extension(TimeSpan)
{
///
@@ -166,62 +224,42 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
///
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.timespan.fromdays?view=net-11.0#system-timespan-fromdays(system-int32-system-int32-system-int64-system-int64-system-int64-system-int64)
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.timespan.fromhours?view=net-11.0#system-timespan-fromhours(system-int32-system-int64-system-int64-system-int64-system-int64)
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.timespan.fromminutes?view=net-11.0#system-timespan-fromminutes(system-int64-system-int64-system-int64-system-int64)
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.timespan.fromseconds?view=net-11.0#system-timespan-fromseconds(system-int64-system-int64-system-int64)
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.timespan.frommilliseconds?view=net-11.0#system-timespan-frommilliseconds(system-int64-system-int64)
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.timespan.frommicroseconds?view=net-11.0#system-timespan-frommicroseconds(system-int64)
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
#endif
}
diff --git a/src/Split/net461/TimeSpanPolyfill.cs b/src/Split/net461/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/net461/TimeSpanPolyfill.cs
+++ b/src/Split/net461/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net462/TimeSpanPolyfill.cs b/src/Split/net462/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/net462/TimeSpanPolyfill.cs
+++ b/src/Split/net462/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net47/TimeSpanPolyfill.cs b/src/Split/net47/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/net47/TimeSpanPolyfill.cs
+++ b/src/Split/net47/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net471/TimeSpanPolyfill.cs b/src/Split/net471/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/net471/TimeSpanPolyfill.cs
+++ b/src/Split/net471/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net472/TimeSpanPolyfill.cs b/src/Split/net472/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/net472/TimeSpanPolyfill.cs
+++ b/src/Split/net472/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net48/TimeSpanPolyfill.cs b/src/Split/net48/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/net48/TimeSpanPolyfill.cs
+++ b/src/Split/net48/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net481/TimeSpanPolyfill.cs b/src/Split/net481/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/net481/TimeSpanPolyfill.cs
+++ b/src/Split/net481/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net5.0/TimeSpanPolyfill.cs b/src/Split/net5.0/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/net5.0/TimeSpanPolyfill.cs
+++ b/src/Split/net5.0/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net6.0/TimeSpanPolyfill.cs b/src/Split/net6.0/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/net6.0/TimeSpanPolyfill.cs
+++ b/src/Split/net6.0/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net7.0/TimeSpanPolyfill.cs b/src/Split/net7.0/TimeSpanPolyfill.cs
index c9e91081..7306e9ae 100644
--- a/src/Split/net7.0/TimeSpanPolyfill.cs
+++ b/src/Split/net7.0/TimeSpanPolyfill.cs
@@ -19,6 +19,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -85,51 +128,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/net8.0/TimeSpanPolyfill.cs b/src/Split/net8.0/TimeSpanPolyfill.cs
index c9e91081..7306e9ae 100644
--- a/src/Split/net8.0/TimeSpanPolyfill.cs
+++ b/src/Split/net8.0/TimeSpanPolyfill.cs
@@ -19,6 +19,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -85,51 +128,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/netcoreapp2.0/TimeSpanPolyfill.cs b/src/Split/netcoreapp2.0/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/netcoreapp2.0/TimeSpanPolyfill.cs
+++ b/src/Split/netcoreapp2.0/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/netcoreapp2.1/TimeSpanPolyfill.cs b/src/Split/netcoreapp2.1/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/netcoreapp2.1/TimeSpanPolyfill.cs
+++ b/src/Split/netcoreapp2.1/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/netcoreapp2.2/TimeSpanPolyfill.cs b/src/Split/netcoreapp2.2/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/netcoreapp2.2/TimeSpanPolyfill.cs
+++ b/src/Split/netcoreapp2.2/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/netcoreapp3.0/TimeSpanPolyfill.cs b/src/Split/netcoreapp3.0/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/netcoreapp3.0/TimeSpanPolyfill.cs
+++ b/src/Split/netcoreapp3.0/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/netcoreapp3.1/TimeSpanPolyfill.cs b/src/Split/netcoreapp3.1/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/netcoreapp3.1/TimeSpanPolyfill.cs
+++ b/src/Split/netcoreapp3.1/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/netstandard2.0/TimeSpanPolyfill.cs b/src/Split/netstandard2.0/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/netstandard2.0/TimeSpanPolyfill.cs
+++ b/src/Split/netstandard2.0/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/netstandard2.1/TimeSpanPolyfill.cs b/src/Split/netstandard2.1/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/netstandard2.1/TimeSpanPolyfill.cs
+++ b/src/Split/netstandard2.1/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Split/uap10.0/TimeSpanPolyfill.cs b/src/Split/uap10.0/TimeSpanPolyfill.cs
index 255ad1d2..462545bf 100644
--- a/src/Split/uap10.0/TimeSpanPolyfill.cs
+++ b/src/Split/uap10.0/TimeSpanPolyfill.cs
@@ -38,6 +38,49 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
}
return new((long)ticks);
}
+ const long MaxFastPathTicks = long.MaxValue / 8;
+ static bool IsWithin(long value, long bound) =>
+ value >= -bound && value <= bound;
+ static TimeSpan FromComponents(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ if (IsWithin(days, MaxFastPathTicks / TimeSpan.TicksPerDay) &&
+ IsWithin(hours, MaxFastPathTicks / TimeSpan.TicksPerHour) &&
+ IsWithin(minutes, MaxFastPathTicks / TimeSpan.TicksPerMinute) &&
+ IsWithin(seconds, MaxFastPathTicks / TimeSpan.TicksPerSecond) &&
+ IsWithin(milliseconds, MaxFastPathTicks / TimeSpan.TicksPerMillisecond) &&
+ IsWithin(microseconds, MaxFastPathTicks / MicrosecondsToTicks))
+ {
+ return new(
+ days * TimeSpan.TicksPerDay +
+ hours * TimeSpan.TicksPerHour +
+ minutes * TimeSpan.TicksPerMinute +
+ seconds * TimeSpan.TicksPerSecond +
+ milliseconds * TimeSpan.TicksPerMillisecond +
+ microseconds * MicrosecondsToTicks);
+ }
+ decimal total = microseconds;
+ if (days != 0)
+ {
+ total += (decimal)days * MicrosecondsPerDay;
+ }
+ if (hours != 0)
+ {
+ total += (decimal)hours * MicrosecondsPerHour;
+ }
+ if (minutes != 0)
+ {
+ total += (decimal)minutes * MicrosecondsPerMinute;
+ }
+ if (seconds != 0)
+ {
+ total += (decimal)seconds * MicrosecondsPerSecond;
+ }
+ if (milliseconds != 0)
+ {
+ total += (decimal)milliseconds * MicrosecondsPerMillisecond;
+ }
+ return TicksFromMicroseconds(total);
+ }
extension(TimeSpan)
{
///
@@ -104,51 +147,31 @@ static TimeSpan TicksFromMicroseconds(decimal totalMicroseconds)
/// Initializes a new instance of the structure to a specified number of days, hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromDays(int days, int hours = 0, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)days * MicrosecondsPerDay +
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(days, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of hours, minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromHours(int hours, long minutes = 0, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)hours * MicrosecondsPerHour +
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, hours, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of minutes, seconds, milliseconds, and microseconds.
///
public static TimeSpan FromMinutes(long minutes, long seconds = 0, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)minutes * MicrosecondsPerMinute +
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, minutes, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of seconds, milliseconds, and microseconds.
///
public static TimeSpan FromSeconds(long seconds, long milliseconds = 0, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)seconds * MicrosecondsPerSecond +
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, seconds, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of milliseconds and microseconds.
///
public static TimeSpan FromMilliseconds(long milliseconds, long microseconds = 0) =>
- TicksFromMicroseconds(
- (decimal)milliseconds * MicrosecondsPerMillisecond +
- microseconds);
+ FromComponents(0, 0, 0, 0, milliseconds, microseconds);
///
/// Initializes a new instance of the structure to a specified number of microseconds.
///
public static TimeSpan FromMicroseconds(long microseconds) =>
- TicksFromMicroseconds(microseconds);
+ FromComponents(0, 0, 0, 0, 0, microseconds);
}
}
diff --git a/src/Tests/TimeSpanPolyfillTests.cs b/src/Tests/TimeSpanPolyfillTests.cs
index 3e698d27..6bedb20d 100644
--- a/src/Tests/TimeSpanPolyfillTests.cs
+++ b/src/Tests/TimeSpanPolyfillTests.cs
@@ -176,4 +176,281 @@ public async Task UnitConstants_AgreeWithTicksPer()
await Assert.That(TimeSpan.MillisecondsPerDay).IsEqualTo(TimeSpan.MillisecondsPerHour * TimeSpan.HoursPerDay);
await Assert.That(TimeSpan.MicrosecondsPerDay).IsEqualTo(TimeSpan.MicrosecondsPerHour * TimeSpan.HoursPerDay);
}
+
+ // What the From* factories are specified to do: sum every component exactly, then throw
+ // ArgumentOutOfRangeException when the total does not fit in the tick range.
+ static long? ExpectedTicks(long days, long hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ var ticks =
+ (days * 86_400_000_000m +
+ hours * 3_600_000_000m +
+ minutes * 60_000_000m +
+ seconds * 1_000_000m +
+ milliseconds * 1_000m +
+ microseconds) * 10m;
+ if (ticks < long.MinValue || ticks > long.MaxValue)
+ {
+ return null;
+ }
+
+ return (long) ticks;
+ }
+
+ // The ticks a factory call produced, or null when it threw ArgumentOutOfRangeException.
+ // Any other exception propagates and fails the test.
+ static long? ActualTicks(Func factory)
+ {
+ try
+ {
+ return factory().Ticks;
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ return null;
+ }
+ }
+
+ // Runs every multi-component factory that can take these components and returns a description
+ // of the first one that disagrees with the specification.
+ static string? CompareFactories(int days, int hours, long minutes, long seconds, long milliseconds, long microseconds)
+ {
+ var expected = ExpectedTicks(days, hours, minutes, seconds, milliseconds, microseconds);
+ var actual = ActualTicks(() => TimeSpan.FromDays(days, hours, minutes, seconds, milliseconds, microseconds));
+ if (actual != expected)
+ {
+ return $"FromDays({days}, {hours}, {minutes}, {seconds}, {milliseconds}, {microseconds}): {Describe(actual)} rather than {Describe(expected)}";
+ }
+
+ expected = ExpectedTicks(0, hours, minutes, seconds, milliseconds, microseconds);
+ actual = ActualTicks(() => TimeSpan.FromHours(hours, minutes, seconds, milliseconds, microseconds));
+ if (actual != expected)
+ {
+ return $"FromHours({hours}, {minutes}, {seconds}, {milliseconds}, {microseconds}): {Describe(actual)} rather than {Describe(expected)}";
+ }
+
+ expected = ExpectedTicks(0, 0, minutes, seconds, milliseconds, microseconds);
+ actual = ActualTicks(() => TimeSpan.FromMinutes(minutes, seconds, milliseconds, microseconds));
+ if (actual != expected)
+ {
+ return $"FromMinutes({minutes}, {seconds}, {milliseconds}, {microseconds}): {Describe(actual)} rather than {Describe(expected)}";
+ }
+
+ expected = ExpectedTicks(0, 0, 0, seconds, milliseconds, microseconds);
+ actual = ActualTicks(() => TimeSpan.FromSeconds(seconds, milliseconds, microseconds));
+ if (actual != expected)
+ {
+ return $"FromSeconds({seconds}, {milliseconds}, {microseconds}): {Describe(actual)} rather than {Describe(expected)}";
+ }
+
+ expected = ExpectedTicks(0, 0, 0, 0, milliseconds, microseconds);
+ actual = ActualTicks(() => TimeSpan.FromMilliseconds(milliseconds, microseconds));
+ if (actual != expected)
+ {
+ return $"FromMilliseconds({milliseconds}, {microseconds}): {Describe(actual)} rather than {Describe(expected)}";
+ }
+
+ return null;
+
+ static string Describe(long? ticks)
+ {
+ if (ticks == null)
+ {
+ return "ArgumentOutOfRangeException";
+ }
+
+ return ticks + " ticks";
+ }
+ }
+
+ [Test]
+ [Arguments(0, 0, 0L, 0L, 0L, 0L)]
+ [Arguments(1, 2, 3L, 4L, 5L, 6L)]
+ [Arguments(-1, -2, -3L, -4L, -5L, -6L)]
+ [Arguments(1, -23, 59L, -59L, 999L, -999L)]
+ [Arguments(0, 0, 0L, 0L, 0L, 1L)]
+ [Arguments(0, 0, 0L, 0L, 0L, -1L)]
+ [Arguments(10_675_199, 2, 48L, 5L, 477L, 580L)]
+ [Arguments(10_675_199, 2, 48L, 5L, 477L, 581L)]
+ [Arguments(-10_675_199, -2, -48L, -5L, -477L, -580L)]
+ [Arguments(-10_675_199, -2, -48L, -5L, -477L, -581L)]
+ [Arguments(10_675_200, 0, 0L, 0L, 0L, 0L)]
+ [Arguments(-10_675_200, 0, 0L, 0L, 0L, 0L)]
+ [Arguments(int.MaxValue, int.MaxValue, long.MaxValue, long.MaxValue, long.MaxValue, long.MaxValue)]
+ [Arguments(int.MinValue, int.MinValue, long.MinValue, long.MinValue, long.MinValue, long.MinValue)]
+ [Arguments(int.MaxValue, int.MinValue, long.MaxValue, long.MinValue, long.MaxValue, long.MinValue)]
+ [Arguments(0, 0, 0L, 0L, 0L, long.MaxValue)]
+ [Arguments(0, 0, 0L, 0L, 0L, long.MinValue)]
+ [Arguments(0, 0, 0L, 0L, long.MaxValue, long.MinValue)]
+ [Arguments(0, 0, long.MaxValue, long.MinValue, 0L, 0L)]
+ public async Task From_Components_MatchSpecification(int days, int hours, long minutes, long seconds, long milliseconds, long microseconds) =>
+ await Assert.That(CompareFactories(days, hours, minutes, seconds, milliseconds, microseconds)).IsNull();
+
+ // The largest and smallest totals that fit: +/-922337203685477580 microseconds
+ [Test]
+ public async Task From_Components_TickRangeBoundaries()
+ {
+ const long maxMicroseconds = long.MaxValue / 10;
+
+ await Assert.That(TimeSpan.FromMilliseconds(0, maxMicroseconds).Ticks).IsEqualTo(9223372036854775800L);
+ await Assert.That(TimeSpan.FromMilliseconds(0, -maxMicroseconds).Ticks).IsEqualTo(-9223372036854775800L);
+ await Assert.That(() => TimeSpan.FromMilliseconds(0, maxMicroseconds + 1)).Throws();
+ await Assert.That(() => TimeSpan.FromMilliseconds(0, -maxMicroseconds - 1)).Throws();
+
+ // reached through every unit at once
+ await Assert.That(TimeSpan.FromDays(10_675_199, 2, 48, 5, 477, 580).Ticks).IsEqualTo(9223372036854775800L);
+ await Assert.That(() => TimeSpan.FromDays(10_675_199, 2, 48, 5, 477, 581)).Throws();
+ await Assert.That(TimeSpan.FromDays(-10_675_199, -2, -48, -5, -477, -580).Ticks).IsEqualTo(-9223372036854775800L);
+ await Assert.That(() => TimeSpan.FromDays(-10_675_199, -2, -48, -5, -477, -581)).Throws();
+
+ // components far out of range that cancel back into range
+ await Assert.That(TimeSpan.FromMinutes(150_000_000_000_000, -9_000_000_000_000_000 + 5, 0, 0).Ticks).IsEqualTo(5 * TimeSpan.TicksPerSecond);
+ await Assert.That(TimeSpan.FromSeconds(long.MaxValue / 1000, -(long.MaxValue / 1000) * 1000, 7).Ticks).IsEqualTo(70L);
+ await Assert.That(TimeSpan.FromMilliseconds(long.MaxValue / 1000, -(long.MaxValue / 1000) * 1000 - 3).Ticks).IsEqualTo(-30L);
+
+ // components that are each in range but overflow together
+ await Assert.That(() => TimeSpan.FromDays(6_000_000, 0, 0, 6_000_000L * 86_400)).Throws();
+ await Assert.That(() => TimeSpan.FromSeconds(long.MaxValue / 10_000_000, long.MaxValue / 10_000, 0)).Throws();
+ }
+
+ // Every component on its own, around each power of two and each power of ten, so that whatever
+ // magnitude an implementation switches arithmetic at is covered from both sides.
+ [Test]
+ public async Task From_Components_SingleComponentMagnitudes()
+ {
+ var magnitudes = new List {0, 1, long.MaxValue};
+ for (var shift = 1; shift < 63; shift++)
+ {
+ magnitudes.Add((1L << shift) - 1);
+ magnitudes.Add(1L << shift);
+ magnitudes.Add((1L << shift) + 1);
+ }
+
+ var power = 1L;
+ for (var exponent = 1; exponent < 19; exponent++)
+ {
+ power *= 10;
+ magnitudes.Add(power - 1);
+ magnitudes.Add(power);
+ magnitudes.Add(power + 1);
+ }
+
+ // the limits of each unit: the last value that fits in the tick range, and its neighbours
+ foreach (var ticksPerUnit in new[] {10L, TimeSpan.TicksPerMillisecond, TimeSpan.TicksPerSecond, TimeSpan.TicksPerMinute, TimeSpan.TicksPerHour, TimeSpan.TicksPerDay})
+ {
+ for (var divisor = 1; divisor <= 16; divisor++)
+ {
+ var limit = long.MaxValue / divisor / ticksPerUnit;
+ magnitudes.Add(limit - 1);
+ magnitudes.Add(limit);
+ magnitudes.Add(limit + 1);
+ }
+ }
+
+ var values = new HashSet {long.MinValue};
+ foreach (var magnitude in magnitudes)
+ {
+ values.Add(magnitude);
+ values.Add(-magnitude);
+ }
+
+ var failures = new List();
+ foreach (var value in values)
+ {
+ Check(CompareFactories(0, 0, 0, 0, 0, value));
+ Check(CompareFactories(0, 0, 0, 0, value, 0));
+ Check(CompareFactories(0, 0, 0, value, 0, 0));
+ Check(CompareFactories(0, 0, value, 0, 0, 0));
+ if (value is >= int.MinValue and <= int.MaxValue)
+ {
+ Check(CompareFactories(0, (int) value, 0, 0, 0, 0));
+ Check(CompareFactories((int) value, 0, 0, 0, 0, 0));
+ }
+ }
+
+ await Assert.That(string.Join(Environment.NewLine, failures)).IsEqualTo(string.Empty);
+
+ void Check(string? failure)
+ {
+ if (failure != null && failures.Count < 20)
+ {
+ failures.Add(failure);
+ }
+ }
+ }
+
+ [Test]
+ public async Task From_Components_Random_MatchSpecification()
+ {
+ var random = new Random(20240917);
+ var failures = new List();
+ for (var index = 0; index < 5_000; index++)
+ {
+ var failure = CompareFactories(
+ (int) Next(31),
+ (int) Next(31),
+ Next(63),
+ Next(63),
+ Next(63),
+ Next(63));
+ if (failure != null && failures.Count < 20)
+ {
+ failures.Add(failure);
+ }
+ }
+
+ await Assert.That(string.Join(Environment.NewLine, failures)).IsEqualTo(string.Empty);
+
+ // A signed value with a random number of significant bits, so that small, medium and
+ // overflowing magnitudes are all common. One call in four returns zero.
+ long Next(int maxBits)
+ {
+ if (random.Next(4) == 0)
+ {
+ return 0;
+ }
+
+ var bits = random.Next(1, maxBits + 1);
+ var buffer = new byte[8];
+ random.NextBytes(buffer);
+ var value = (long) (BitConverter.ToUInt64(buffer, 0) >> (64 - bits));
+ if (random.Next(2) == 0)
+ {
+ return -value;
+ }
+
+ return value;
+ }
+ }
+
+ [Test]
+ public async Task FromMicroseconds_Long_MatchesSpecification()
+ {
+ // Below net9 a long argument binds to the BCL's FromMicroseconds(double) where that exists
+ // (net7 and net8), which rounds. Values a double holds exactly behave the same everywhere.
+ foreach (var value in new[] {0L, 1L, -1L, 999L, 1_000_000L, -86_400_000_000L, 1L << 40, -(1L << 52)})
+ {
+ await Assert.That(TimeSpan.FromMicroseconds(value).Ticks).IsEqualTo(value * 10);
+ }
+
+ // 2^53 + 1 is not representable as a double, so this tells the exact overload apart
+ var exact = TimeSpan.FromMicroseconds(9_007_199_254_740_993L).Ticks == 90_071_992_547_409_930L;
+ if (!exact)
+ {
+ return;
+ }
+
+ const long maxMicroseconds = long.MaxValue / 10;
+ foreach (var divisor in new long[] {1, 2, 4, 7, 8, 9, 16})
+ {
+ foreach (var delta in new long[] {-1, 0, 1})
+ {
+ var value = maxMicroseconds / divisor + delta;
+ await Assert.That(ActualTicks(() => TimeSpan.FromMicroseconds(value))).IsEqualTo(ExpectedTicks(0, 0, 0, 0, 0, value));
+ await Assert.That(ActualTicks(() => TimeSpan.FromMicroseconds(-value))).IsEqualTo(ExpectedTicks(0, 0, 0, 0, 0, -value));
+ }
+ }
+
+ await Assert.That(() => TimeSpan.FromMicroseconds(long.MaxValue)).Throws();
+ await Assert.That(() => TimeSpan.FromMicroseconds(long.MinValue)).Throws();
+ }
}