Помножте часовий проміжок у .NET


86

Як помножити об'єкт TimeSpan у C #? Якщо припустити, що змінна durationє TimeSpan , я хотів би, наприклад

duration*5

Але це видає мені помилку "Оператор * не може бути застосований до типів TimeSpan і int". Ось моє поточне рішення

duration+duration+duration+duration+duration

Але це не поширюється на нецілі кратні, наприклад. duration * 3.5


5
Це справді очевидна вимога і проста у реалізації. Цікаво, чому держава-член не думала включати множення та ділення як стандартні оператори?
Енді,

Відповіді:


103

З цієї статті

TimeSpan duration = TimeSpan.FromMinutes(1);
duration = TimeSpan.FromTicks(duration.Ticks * 12);
Console.WriteLine(duration);     

4
Дякую, що я використавTimeSpan.FromTicks((long)(duration.Ticks*multiplier))
полковник Панік

2
Я волів би використовувати методи розширення. Як пропонував Стівен Хьюлетт у своїх відповідях на це питання.
Mike de Klerk

11
@MikedeKlerk Погодився, але це більше синтаксичний цукор. ОП все ще має знати корінь відповіді, щоб його можна було застосувати всередині будь-якого методу, розширення чи ні
Джастін Піхоні

2
Дякую за комплімент, але я відчуваю себе зобов'язаним зазначити, що @JustinPihony відповів майже за два роки до того, як я відповів, і саме інформація у його відповіді дозволила мені написати свою.
Stephen Hewlett

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 секунд.


Методи розширення є найбільш зручним рішенням таких проблем.
Mike de Klerk

Параметр множника може мати тип 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 .

Якщо ви спробуєте наведений вище код у програмі Console , наприклад, під керуванням .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, просвітницьше бачити, що говорить Іммо :

.NET Core - це версія .NET з відкритим кодом, міжплатформна та швидка версія. Через його паралельний характер він може вносити зміни, які ми не можемо ризикувати застосувати назад до .NET Framework. Це означає, що .NET Core з часом отримає нові API та мовні функції, які не може .NET Framework. У Build ми продемонстрували демонстрацію того, як API файлів швидше працюють на .NET Core. Якщо ми внесемо ті самі зміни в .NET Framework, ми могли б зламати існуючі програми, і ми не хочемо цього робити.


2

Вам потрібно вказати, якого члена ви хочете помножити на 5 -> TimeSpan.TotalMinutes * 5


1
Це справді працює, але приємнішим загальним рішенням є множення кліщів IMHO.
Роб Левін

1
Ні, TimeSpan - це скаляр. T * 5також повинен помножити години і секунди.
Хенк Холтерман

1
@HenkHolterman, але TotalMinutesце загальна тривалість проміжку часу, виражена в хвилинах, тому, якщо проміжок часу представляє годину і 10 хвилин і 30 секунд, TotalMinutes поверне 70,5.
phoog

1
@HenkHolterman Як відзначає phoog, TotalMinutesвластивість - це Double, що дає загальну кількість хвилин усього TimeSpan, враховуючи всі інші поля. Це рішення працює однаково, хоча Ticksвидається більш приємним підходом. Але візьміть до уваги, що пізніше кліщі потрібно буде перетворити на хвилини, якщо ви хочете показати користувачеві якусь інформацію, яка має сенс.
PedroC88

Погодившись, я відреагував на першу частину речення. TotalMinutes насправді не є композитором.
Хенк Холтерман

2

Проблема в тому, що ви хочете помножити проміжок часу. Найпростіший обхідний шлях - використання кліщів. напр.

 var ticks = TimeSpan.FromMinutes(1).Ticks;
 var newTimeSpan = TimeSpan.FromTicks(ticks*5);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.