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


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

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.


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


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


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ć.


2

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


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);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.