Multiplier TimeSpan dans .NET

86

Comment multiplier un objet TimeSpan en C #? En supposant que la variable durationest un TimeSpan , je voudrais, par exemple

duration*5

Mais cela me donne une erreur "opérateur * ne peut pas être appliqué aux types TimeSpan et int". Voici ma solution de contournement actuelle

duration+duration+duration+duration+duration

Mais cela ne s'étend pas aux multiples non entiers, par exemple. duration * 3.5

Colonel Panic
la source
5
C'est une exigence vraiment évidente et simple à mettre en œuvre. Je me demande pourquoi MS n'a pas pensé à inclure la multiplication et la division comme opérateurs standard?
Andy

Réponses:

103

De cet article

TimeSpan duration = TimeSpan.FromMinutes(1);
duration = TimeSpan.FromTicks(duration.Ticks * 12);
Console.WriteLine(duration);     
Justin Pihony
la source
4
Merci j'ai utiliséTimeSpan.FromTicks((long)(duration.Ticks*multiplier))
Colonel Panic
2
Je préférerais utiliser des méthodes d'extension. Comme suggéré par Stephen Hewlett dans ses réponses à cette question.
Mike de Klerk
11
@MikedeKlerk D'accord, mais c'est du sucre plus syntaxique. L'OP a encore besoin de connaître la racine de la réponse afin qu'elle puisse être appliquée à l'intérieur de n'importe quelle méthode, extension ou non
Justin Pihony
2
Merci pour le compliment, mais je me sens obligé de souligner que @JustinPihony a répondu près de deux ans avant moi et que ce sont les informations contenues dans sa réponse qui m'ont permis d'écrire la mienne.
Stephen Hewlett
45

Pour ceux qui souhaitent copier et coller:

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

Exemple d'utilisation:

using Utility;

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

t se terminera en 150 secondes.

Stephen Hewlett
la source
Les méthodes d'extension sont la solution la plus pratique à ce genre de problèmes.
Mike de Klerk
Le paramètre multiplicateur peut être de type long sans frais supplémentaires.
tm1
13

La TimeSpanstructure n'entraîne pas de surcharge pour l' *opérateur, vous devez donc le faire vous-même:

var result = TimeSpan.FromTicks(duration.Ticks * 5);
Kent Boogaart
la source
5

Vous pouvez utiliser les données internes de TimeSpan, à savoir les ticks.

TimeSpan day = TimeSpan.FromDays(1);
TimeSpan week = TimeSpan.FromTicks(day.Ticks * 7);
Kendall Frey
la source
3

Multiply est maintenant disponible pour TimeSpan !!!

Mais uniquement pour .NET Core et .NET Standard .

Depuis .NET Core 2.0 (ou .NET Standard 2.1 ), vous pouvez exécuter avec succès le code suivant:

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

Limites

Néanmoins, il est important de noter ( comme décrit dans le document ) que cela s'applique uniquement à .NET Core 2.0 + et .NET Standard 2.1 +.

À partir d'aujourd'hui (26 novembre 2019), le code ci-dessus échouera même dans la dernière version de .NET Framework : 4.8 .

Si vous essayez le code ci-dessus dans une application de console , par exemple, exécutant .NET Core 1.1 ou inférieur, ou .NET Framework 4.8 ou inférieur, vous serez renvoyé l'exception suivante:

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

Pourquoi pas dans .NET Framework?

Afin de comprendre pourquoi diable nous ne pouvons pas utiliser le code ci-dessus dans .NET Framework, il est instructif de voir ce que dit Immo :

.NET Core est la version open source, multiplateforme et à évolution rapide de .NET. En raison de sa nature côte à côte, il peut prendre des modifications que nous ne pouvons pas risquer de réappliquer à .NET Framework. Cela signifie que .NET Core obtiendra de nouvelles API et fonctionnalités de langage au fil du temps que .NET Framework ne peut pas. Lors de Build, nous avons montré une démonstration de la rapidité des API de fichiers sur .NET Core. Si nous mettons ces mêmes modifications dans .NET Framework, nous pourrions interrompre les applications existantes, et nous ne voulons pas le faire.

Deczaloth
la source
2

Vous devez spécifier quel membre vous voulez multiplier par 5 -> TimeSpan.TotalMinutes * 5

PedroC88
la source
1
Cela fonctionne - mais une solution générale plus agréable consiste à multiplier les tiques à mon humble avis.
Rob Levine
1
Non, un TimeSpan est un scalaire. T * 5devrait aussi multiplier les heures et les secondes.
Henk Holterman
1
@HenkHolterman mais TotalMinutesest la durée totale de l'intervalle de temps exprimée en minutes, donc si l'intervalle de temps représente une heure et 10 minutes et 30 secondes, TotalMinutes renverrait 70,5.
phoog
1
@HenkHolterman Comme le note le phoog, la TotalMinutespropriété est un double donnant le nombre total de minutes de tout le TimeSpan, en tenant compte de tous les autres champs. Cette solution fonctionne de la même manière bien Ticksqu'elle semble être une approche plus agréable. Mais tenez compte du fait que les ticks devront plus tard être transformés en minutes si vous souhaitez montrer à l'utilisateur des informations qui ont du sens.
PedroC88
D'accord, j'ai réagi à la première partie de la phrase. TotalMinutes n'est pas vraiment un membre compositeur.
Henk Holterman
2

Le problème ici est que vous souhaitez multiplier la durée. La solution de contournement la plus simple consiste à utiliser des graduations. par exemple.

 var ticks = TimeSpan.FromMinutes(1).Ticks;
 var newTimeSpan = TimeSpan.FromTicks(ticks*5);
Marcin
la source