Pomnóż TimeSpan w .NET

86

Jak pomnożyć obiekt TimeSpan w C #? Zakładając, że zmienna durationjest TimeSpan , chciałbym na przykład

duration*5

Ale to daje mi błąd „operator * nie może być zastosowany do typów TimeSpan i int”. Oto moje obecne obejście

duration+duration+duration+duration+duration

Ale to nie dotyczy wielokrotności niecałkowitych, np. duration * 3.5

Colonel Panic
źródło
5
To jest naprawdę oczywiste wymaganie i proste do wdrożenia. Zastanawiam się, dlaczego MS nie pomyślało o uwzględnieniu mnożenia i dzielenia jako standardowych operatorów?
Andy

Odpowiedzi:

103

Z tego artykułu

TimeSpan duration = TimeSpan.FromMinutes(1);
duration = TimeSpan.FromTicks(duration.Ticks * 12);
Console.WriteLine(duration);     
Justin Pihony
źródło
4
Dzięki, użyłemTimeSpan.FromTicks((long)(duration.Ticks*multiplier))
Colonel Panic
2
Wolałbym raczej używać metod rozszerzających. Tak jak sugerował Stephen Hewlett w swoich odpowiedziach na to pytanie.
Mike de Klerk
11
@MikedeKlerk Zgoda, ale to jest bardziej syntaktyczny cukier. OP nadal musi znać źródło odpowiedzi, aby można ją było zastosować w dowolnej metodzie, rozszerzeniu lub nie
Justin Pihony
2
Dziękuję za komplement, ale czuję się zobowiązany do wskazania, że ​​@JustinPihony odpowiedział prawie dwa lata wcześniej i to właśnie informacje zawarte w jego odpowiedzi pozwoliły mi napisać moją.
Stephen Hewlett
45

Dla tych, którzy chcą kopiować i wklejać:

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

Przykładowe zastosowanie:

using Utility;

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

t zakończy się jako 150 sekund.

Stephen Hewlett
źródło
Metody rozszerzające są najwygodniejszym rozwiązaniem tego rodzaju problemów.
Mike de Klerk
Parametr mnożnika mógłby mieć typ długi bez dodatkowych kosztów.
tm1
13

TimeSpanStruktura nie zapewnia przeciążenie dla *operatora, więc trzeba to zrobić samemu:

var result = TimeSpan.FromTicks(duration.Ticks * 5);
Kent Boogaart
źródło
5

Możesz użyć wewnętrznych danych TimeSpan, a mianowicie tików.

TimeSpan day = TimeSpan.FromDays(1);
TimeSpan week = TimeSpan.FromTicks(day.Ticks * 7);
Kendall Frey
źródło
3

Funkcja Multiply jest teraz dostępna dla TimeSpan !!!

Ale tylko dla .NET Core i .NET Standard .

Od .NET Core 2.0 (lub .NET Standard 2.1 ) można pomyślnie uruchomić następujący kod:

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

Ograniczenia

Niemniej jednak należy zauważyć ( zgodnie z opisem w dokumentacji ), że dotyczy to tylko .NET Core 2.0 + i .NET Standard 2.1 +.

Na dzień dzisiejszy (26 listopada 2019) powyższy kod zawiedzie nawet w najnowszej wersji .NET Framework : 4.8 .

Jeśli wypróbujesz powyższy kod w aplikacji konsoli , na przykład z systemem .NET Core 1.1 lub starszym albo .NET Framework 4.8 lub niższym, zostanie zgłoszony następujący wyjątek:

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

Dlaczego nie w .NET Framework?

Aby zrozumieć, dlaczego nie możemy użyć powyższego kodu w .NET Framework, pouczające jest to, co mówi Immo :

NET Core to otwarta, wieloplatformowa i szybko rozwijająca się wersja platformy .NET. Ze względu na swoją równoległą naturę może on wprowadzać zmiany, których nie możemy ryzykować zastosowania z powrotem do .NET Framework. Oznacza to, że .NET Core z czasem otrzyma nowe interfejsy API i funkcje językowe, których nie może zapewnić .NET Framework. W Build pokazaliśmy, jak interfejsy API plików są szybsze w .NET Core. Gdybyśmy wprowadzili te same zmiany do .NET Framework, moglibyśmy zepsuć istniejące aplikacje, a nie chcemy tego robić.

Deczaloth
źródło
2

Musisz określić, który członek ma zostać pomnożony przez 5 -> TimeSpan.TotalMinutes * 5

PedroC88
źródło
1
To działa - ale ładniejszym rozwiązaniem ogólnym jest pomnożenie kleszczy IMHO.
Rob Levine,
1
Nie, TimeSpan to wartość skalarna. T * 5powinien również pomnożyć godziny i sekundy.
Henk Holterman
1
@HenkHolterman, ale TotalMinutesjest to całkowity czas trwania przedziału czasu wyrażony w minutach, więc jeśli przedział czasu reprezentuje godzinę oraz 10 minut i 30 sekund, TotalMinutes zwróci wartość 70,5.
phoog
1
@HenkHolterman Jak zauważa phoog, TotalMinuteswłaściwość jest Double, podając całkowitą liczbę minut z całego TimeSpan, biorąc pod uwagę wszystkie inne pola. To rozwiązanie działa tak samo, chociaż Tickswydaje się być przyjemniejszym podejściem. Ale weź pod uwagę, że Kleszcze będą później musiały zostać przekształcone w minuty, jeśli chcesz pokazać użytkownikowi jakieś sensowne informacje.
PedroC88
Zgoda, zareagowałem na pierwszą część zdania. TotalMinutes tak naprawdę nie jest członkiem komponującym.
Henk Holterman
2

Problem polega na tym, że chcesz pomnożyć przedział czasu. Najprostszym obejściem jest użycie znaczników. na przykład.

 var ticks = TimeSpan.FromMinutes(1).Ticks;
 var newTimeSpan = TimeSpan.FromTicks(ticks*5);
Marcin
źródło