Multiplique TimeSpan em .NET

86

Como faço para multiplicar um objeto TimeSpan em C #? Supondo que a variável durationseja um TimeSpan , gostaria, por exemplo

duration*5

Mas isso me dá um erro "operador * não pode ser aplicado aos tipos TimeSpan e int". Aqui está minha solução alternativa atual

duration+duration+duration+duration+duration

Mas isso não se estende a múltiplos não inteiros, por exemplo. duration * 3.5

Coronel Panic
fonte
5
Este é um requisito realmente óbvio e simples de implementar. Eu me pergunto por que a MS não pensou em incluir multiplicar e dividir como operadores padrão?
Andy

Respostas:

103

Deste artigo

TimeSpan duration = TimeSpan.FromMinutes(1);
duration = TimeSpan.FromTicks(duration.Ticks * 12);
Console.WriteLine(duration);     
Justin Pihony
fonte
4
Obrigado, useiTimeSpan.FromTicks((long)(duration.Ticks*multiplier))
Coronel Panic
2
Eu prefiro usar métodos de extensão. Como sugerido por Stephen Hewlett em suas respostas a esta pergunta.
Mike de Klerk,
11
@MikedeKlerk Concordo, mas isso é mais açúcar sintático. O OP ainda precisa saber a raiz da resposta para que possa ser aplicado dentro de qualquer método, extensão ou não
Justin Pihony
2
Obrigado pelo elogio, mas me sinto na obrigação de ressaltar que @JustinPihony respondeu quase dois anos antes de mim e foi a informação em sua resposta que me permitiu escrever a minha.
Stephen Hewlett,
45

Para quem deseja copiar e colar:

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

Exemplo de uso:

using Utility;

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

t terminará em 150 segundos.

Stephen Hewlett
fonte
Os métodos de extensão são a solução mais conveniente para esse tipo de problema.
Mike de Klerk,
O parâmetro do multiplicador pode ter tipo longo sem custos adicionais.
tm1
13

A TimeSpanestrutura não sobrecarrega o *operador, portanto, você mesmo deve fazer isso:

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

Você pode usar os dados internos do TimeSpan, ou seja, ticks.

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

Multiply agora está disponível para TimeSpan !!!

Mas apenas para .NET Core e .NET Standard .

Desde o .NET Core 2.0 (ou .NET Standard 2.1 ), você pode executar com êxito o seguinte código:

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

Limitações

No entanto, é importante observar ( conforme descrito no documento ) que isso se aplica apenas a .NET Core 2.0 + e .NET Standard 2.1 +.

A partir de hoje (26 de novembro de 2019), o código acima irá falhar mesmo na versão mais recente do .NET Framework : 4.8 .

Se você tentar o código acima em um aplicativo de console , por exemplo, executando o .NET Core 1.1 ou inferior, ou .NET Framework 4.8 ou inferior, você verá a seguinte exceção:

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

Por que não no .NET Framework?

Para entender por que diabos não podemos usar o código acima no .NET Framework, é esclarecedor ver o que Immo diz :

.NET Core é a versão de código aberto, multiplataforma e de rápida evolução do .NET. Por causa de sua natureza lado a lado, ele pode aceitar alterações que não podemos arriscar aplicar de volta ao .NET Framework. Isso significa que o .NET Core obterá novas APIs e recursos de linguagem com o tempo que o .NET Framework não consegue. No Build, mostramos uma demonstração de como as APIs de arquivo são mais rápidas no .NET Core. Se colocarmos essas mesmas alterações no .NET Framework, poderemos quebrar os aplicativos existentes, e não queremos fazer isso.

Deczaloth
fonte
2

Você precisa especificar qual membro deseja multiplicar por 5 -> TimeSpan.TotalMinutes * 5

PedroC88
fonte
1
Isso funciona - mas uma solução geral mais agradável é multiplicar os carrapatos IMHO.
Rob Levine
1
Não, um TimeSpan é um escalar. T * 5deve multiplicar as horas e os segundos também.
Henk Holterman
1
@HenkHolterman mas TotalMinutesé a duração total do intervalo de tempo expresso em minutos, então se o intervalo de tempo representar uma hora e 10 minutos e 30 segundos, TotalMinutes retornaria 70,5.
phoog
1
@HenkHolterman Como o phoog observa, a TotalMinutespropriedade é um Double dando a quantidade total de minutos de todo o TimeSpan, levando todos os outros campos em consideração. Esta solução funciona da mesma forma, embora Tickspareça uma abordagem mais agradável. Mas leve em consideração que os Ticks posteriormente precisarão ser transformados em minutos se você quiser mostrar ao usuário alguma informação que faça sentido.
PedroC88
Concordo, reagi à primeira parte da frase. TotalMinutes não é realmente um membro de composição.
Henk Holterman
2

O problema aqui é que você deseja multiplicar o intervalo de tempo. A solução mais simples é usar ticks. por exemplo.

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