Умножение TimeSpan в .NET

86

Как мне умножить объект TimeSpan в C #? Предполагая, что переменная duration- это TimeSpan , я бы хотел, например,

duration*5

Но это дает мне ошибку «оператор * не может применяться к типам TimeSpan и int». Вот мой текущий обходной путь

duration+duration+duration+duration+duration

Но это не распространяется на нецелые числа, например. duration * 3.5

Полковник Паник
источник
5
Это действительно очевидное требование, и его легко реализовать. Интересно, почему MS не подумала включить умножение и деление в стандартные операторы?
Энди

Ответы:

103

Из этой статьи

TimeSpan duration = TimeSpan.FromMinutes(1);
duration = TimeSpan.FromTicks(duration.Ticks * 12);
Console.WriteLine(duration);     
Джастин Пихони
источник
4
Спасибо, что использовалTimeSpan.FromTicks((long)(duration.Ticks*multiplier))
полковник Паник
2
Я бы предпочел использовать методы расширения. Как предложил Стивен Хьюлетт в его ответах на этот вопрос.
Майк де Клерк
11
@MikedeKlerk Согласен, но это скорее синтаксический сахар. OP по-прежнему должен знать корень ответа, чтобы его можно было применить внутри любого метода, расширения или нет,
Джастин Пихони
2
Спасибо за комплимент, но я считаю своим долгом отметить, что @JustinPihony ответил почти на два года раньше меня, и именно информация в его ответе позволила мне написать свой.
Стивен Хьюлетт
45

Для желающих скопировать и вставить:

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));
        }
    }
}

Пример использования:

using Utility;

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

t будет 150 секунд.

Стивен Хьюлетт
источник
Методы расширения - наиболее удобное решение таких проблем.
Майк де Клерк
Параметр множителя может иметь тип long без дополнительных затрат.
tm1
13

TimeSpanСтруктура не обеспечивает перегрузку для *оператора, так что вы должны сделать это самостоятельно:

var result = TimeSpan.FromTicks(duration.Ticks * 5);
Кент Бугарт
источник
5

Вы можете использовать внутренние данные TimeSpan, а именно тики.

TimeSpan day = TimeSpan.FromDays(1);
TimeSpan week = TimeSpan.FromTicks(day.Ticks * 7);
Кендалл Фрей
источник
3

Умножение теперь доступно для TimeSpan !!!

Но только для .NET Core и .NET Standard .

Начиная с .NET Core 2.0 (или .NET Standard 2.1 ) вы можете успешно запустить следующий код:

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

Ограничения

Тем не менее, важно отметить ( как описано в документе ), что это применимо только для .NET Core 2.0 + и .NET Standard 2.1 +.

На сегодняшний день (26 ноября 2019 г.) приведенный выше код не работает даже в последней версии .NET Framework : 4.8 .

Если вы попробуете приведенный выше код в консольном приложении, например, с .NET Core 1.1 или более ранней версии или .NET Framework 4.8 или более ранней версии, вы получите следующее исключение:

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

Почему не в .NET Framework?

Чтобы понять, почему мы не можем использовать приведенный выше код в .NET Framework, полезно узнать, что говорит Immo :

.NET Core - это кроссплатформенная быстро развивающаяся версия .NET с открытым исходным кодом. Из-за своего параллельного характера он может принимать изменения, которые мы не можем рискнуть применить обратно к .NET Framework. Это означает, что .NET Core со временем получит новые API и языковые функции, которых нет в .NET Framework. На Build мы показали демонстрацию того, как файловые API работают быстрее в .NET Core. Если мы внесем те же изменения в .NET Framework, мы можем сломать существующие приложения, а мы не хотим этого делать.

Deczaloth
источник
2

Вам необходимо указать, какой член вы хотите умножить на 5 -> TimeSpan.TotalMinutes * 5

PedroC88
источник
1
Это действительно работает, но более хорошее общее решение - умножить тики ИМХО.
Роб Левин
1
Нет, TimeSpan - это скаляр. T * 5также следует умножить часы и секунды.
Хенк Холтерман
1
@HenkHolterman, но TotalMinutes- это общая продолжительность промежутка времени, выраженная в минутах, поэтому, если промежуток времени представляет час 10 минут и 30 секунд, TotalMinutes вернет 70,5.
phoog
1
@HenkHolterman Как отмечает фог, TotalMinutesсвойство - это Double, дающее общее количество минут всего TimeSpan с учетом всех остальных полей. Это решение работает так же, хотя Ticksкажется более приятным. Но учтите, что тики позже нужно будет преобразовать в минуты, если вы хотите показать пользователю некоторую информацию, которая имеет смысл.
PedroC88
Согласился, отреагировал на первую часть предложения. TotalMinutes на самом деле не является составным участником.
Хенк Холтерман
2

Проблема в том, что вы хотите умножить временной интервал. Самый простой обходной путь - использовать галочки. например.

 var ticks = TimeSpan.FromMinutes(1).Ticks;
 var newTimeSpan = TimeSpan.FromTicks(ticks*5);
Марчин
источник