Multiply TimeSpan in .NET
Asked Answered
T

9

98

How do I multiply a TimeSpan object in C#? Assuming the variable duration is a TimeSpan, I would like, for example

duration*5

But that gives me an error "operator * cannot be applied to types TimeSpan and int". Here's my current workaround

duration+duration+duration+duration+duration

But this doesn't extend to non-integer multiples, eg. duration * 3.5

Trussing answered 28/3, 2012 at 13:59 Comment(0)
P
113

From this article

TimeSpan duration = TimeSpan.FromMinutes(1);
duration = TimeSpan.FromTicks(duration.Ticks * 12);
Console.WriteLine(duration);     
Peridium answered 28/3, 2012 at 14:1 Comment(3)
Thanks I used TimeSpan.FromTicks((long)(duration.Ticks*multiplier))Trussing
I would rather use extension methods. Like suggested by Stephen Hewlett in his answers to this question.Philippians
@MikedeKlerk Agreed, but that is more syntactic sugar. The OP still needs to know the root of the answer so that it can be applied inside any method, extension or notPeridium
B
51

For those wishing to copy and paste:

namespace Utility
{
    public static class TimeSpanExtension
    {
        /// <summary>
        /// Multiplies a timespan by an integer value
        /// </summary>
        public static TimeSpan Multiply(this TimeSpan multiplicand, int multiplier)
        {
            return TimeSpan.FromTicks(multiplicand.Ticks * multiplier);
        }

        /// <summary>
        /// Multiplies a timespan by a double value
        /// </summary>
        public static TimeSpan Multiply(this TimeSpan multiplicand, double multiplier)
        {
            return TimeSpan.FromTicks((long)(multiplicand.Ticks * multiplier));
        }
    }
}

Example Usage:

using Utility;

private static void Example()
{
    TimeSpan t = TimeSpan.FromSeconds(30).Multiply(5);
}

t will end up as 150 seconds.

Bonina answered 11/1, 2013 at 19:45 Comment(3)
Extension methods are the most convenient solution to these kind of problems.Philippians
The multiplier parameter could have type long with no additional costs.Whitman
In case it's useful to anyone, I chose to add overflow checking, throwing if long.MaxValue / multiplier < multiplicand.Ticks OR long.MinValue / multiplier > multiplicand.Ticks, for the int multiplier. Since the implementation in the post floors by casting double-to-long, this same logic should work for the double multiplier.Heehaw
A
14

TimeSpan.Multiply has arrived in .NET Core, and looks like it will arrive in .NET Standard 2.1:

https://learn.microsoft.com/en-us/dotnet/api/system.timespan.op_multiply?view=netstandard-2.1

   var result = 3.0 * TimeSpan.FromSeconds(3);
Ambrosial answered 18/4, 2019 at 7:17 Comment(0)
S
13

The TimeSpan structure does not provide an overload for the * operator, so you have to do this yourself:

var result = TimeSpan.FromTicks(duration.Ticks * 5);
Sitin answered 28/3, 2012 at 14:2 Comment(0)
E
11

Multiply is now available for TimeSpan!!!

But only for .NET Core, .NET Standard and .NET 5+.

Since .NET Core 2.0 (or .NET Standard 2.1) you can successfully run the following code:

Console.WriteLine(TimeSpan.FromSeconds(45) * 3);
// Prints:
// 00:02:15

Limitations

Nevertheless, it is important to note (as described in the docu) that this only applies for .NET Core 2.0+, .NET Standard 2.1+, and of course .NET 5+.

The code above will fail even in the latest .NET Framework version: 4.8 (which is actually the last version of .NET Framework!).

If you try the code above in a Console application, for example, running .NET Core 1.1 or lower, or .NET Framework 4.8 or lower you will be thrown the following exception:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Operator '*' cannot be applied to operands of type 'System.TimeSpan' and 'int''


Why not in .NET Framework?

In order to try to understand why some features will be added to .Net Core but not to .NET Framework, it is enlightening to see what Immo says:

.NET Core is the open source, cross-platform, and fast-moving version of .NET. Because of its side-by-side nature it can take changes that we can’t risk applying back to .NET Framework. This means that .NET Core will get new APIs and language features over time that .NET Framework cannot. At Build we showed a demo how the file APIs are faster on .NET Core. If we put those same changes into .NET Framework we could break existing applications, and we don’t want to do that.

Epididymis answered 26/11, 2019 at 8:54 Comment(1)
The quote from Immo is completely irrelevant to adding a new operator to the TimeSpan type. It can't break any existing code, because there is no old implementation. Perhaps there are code licensing questions, but there's no technical reason .NET Framework can't have this change as well.Scone
M
5

You can use the internal data of TimeSpan, namely ticks.

TimeSpan day = TimeSpan.FromDays(1);
TimeSpan week = TimeSpan.FromTicks(day.Ticks * 7);
Mickelson answered 28/3, 2012 at 14:4 Comment(0)
A
2

You need to specify which member it is you want to multiply by 5 -> TimeSpan.TotalMinutes * 5

Amman answered 28/3, 2012 at 14:1 Comment(4)
No, a TimeSpan is a scalar. T * 5 should multiply the hours and seconds too.Snub
@HenkHolterman but TotalMinutes is the total duration of the timespan expressed in minutes, so if the timespan represents an hour and 10 minutes and 30 seconds, TotalMinutes would return 70.5.Cockerel
@HenkHolterman As phoog notes the TotalMinutes Property is a Double giving the total amount of minutes of the whole TimeSpan, taking all the other fields into account. This solution works the same although Ticks does seem like a nicer approach. But take into account that the Ticks will later need to be transformed into minutes if you want to show the user with some information that makes sense.Amman
Agreed, I reacted to the first part of the sentence. TotalMinutes is not really a compositing member.Snub
B
2

The problem here is that you want to multiply timespan. The simplest workaround is to use ticks. eg.

 var ticks = TimeSpan.FromMinutes(1).Ticks;
 var newTimeSpan = TimeSpan.FromTicks(ticks*5);
Balf answered 28/3, 2012 at 14:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.