Multiplica TimeSpan en .NET

86

¿Cómo multiplico un objeto TimeSpan en C #? Suponiendo que la variable durationes un TimeSpan , me gustaría, por ejemplo

duration*5

Pero eso me da un error "el operador * no se puede aplicar a los tipos TimeSpan e int". Aquí está mi solución actual

duration+duration+duration+duration+duration

Pero esto no se extiende a múltiplos no enteros, por ejemplo. duration * 3.5

Coronel Panic
fuente
5
Este es un requisito realmente obvio y fácil de implementar. Me pregunto por qué MS no pensó en incluir multiplicar y dividir como operadores estándar.
Andy

Respuestas:

103

De este articulo

TimeSpan duration = TimeSpan.FromMinutes(1);
duration = TimeSpan.FromTicks(duration.Ticks * 12);
Console.WriteLine(duration);     
Justin Pihony
fuente
4
Gracias, uséTimeSpan.FromTicks((long)(duration.Ticks*multiplier))
Colonel Panic
2
Prefiero usar métodos de extensión. Como sugirió Stephen Hewlett en sus respuestas a esta pregunta.
Mike de Klerk
11
@MikedeKlerk De acuerdo, pero eso es más azúcar sintáctico. El OP aún necesita saber la raíz de la respuesta para que se pueda aplicar dentro de cualquier método, extensión o no
Justin Pihony
2
Gracias por el cumplido, pero me siento en la obligación de señalar que @JustinPihony respondió casi dos años antes que yo y fue la información en su respuesta la que me permitió escribir la mía.
Stephen Hewlett
45

Para aquellos que deseen copiar y pegar:

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

Ejemplo de uso:

using Utility;

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

t terminará en 150 segundos.

Stephen Hewlett
fuente
Los métodos de extensión son la solución más conveniente para este tipo de problemas.
Mike de Klerk
El parámetro del multiplicador podría tener un tipo largo sin costos adicionales.
tm1
13

La TimeSpanestructura no proporciona una sobrecarga para el *operador, por lo que debe hacerlo usted mismo:

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

Puede utilizar los datos internos de TimeSpan, a saber, ticks.

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

Multiplicar ahora está disponible para TimeSpan !!!

Pero solo para .NET Core y .NET Standard .

Desde .NET Core 2.0 (o .NET Standard 2.1 ) puede ejecutar correctamente el siguiente código:

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

Limitaciones

Sin embargo, es importante tener en cuenta ( como se describe en el documento ) que esto solo se aplica a .NET Core 2.0 + y .NET Standard 2.1 +.

A partir de hoy (26 de noviembre de 2019), el código anterior fallará incluso en la última versión de .NET Framework : 4.8 .

Si prueba el código anterior en una aplicación de consola , por ejemplo, ejecutando .NET Core 1.1 o inferior, o .NET Framework 4.8 o inferior, se le lanzará la siguiente excepción:

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

¿Por qué no en .NET Framework?

Para entender por qué diablos no podemos usar el código anterior en .NET Framework, es esclarecedor ver lo que dice Immo :

.NET Core es la versión de código abierto, multiplataforma y de rápido movimiento de .NET. Debido a su naturaleza paralela, puede tomar cambios que no podemos arriesgarnos a aplicar a .NET Framework. Esto significa que .NET Core obtendrá nuevas API y características de lenguaje con el tiempo que .NET Framework no puede. En Build, mostramos una demostración de cómo las API de archivos son más rápidas en .NET Core. Si ponemos esos mismos cambios en .NET Framework, podríamos romper las aplicaciones existentes, y no queremos hacer eso.

Deczaloth
fuente
2

Debe especificar qué miembro desea multiplicar por 5 -> TimeSpan.TotalMinutes * 5

PedroC88
fuente
1
Esto funciona, pero una mejor solución general es multiplicar las garrapatas en mi humilde opinión.
Rob Levine
1
No, un TimeSpan es un escalar. T * 5también debe multiplicar las horas y los segundos.
Henk Holterman
1
@HenkHolterman pero TotalMinuteses la duración total del intervalo de tiempo expresada en minutos, por lo que si el intervalo de tiempo representa una hora y 10 minutos y 30 segundos, TotalMinutes devolvería 70.5.
phoog
1
@HenkHolterman Como señala phoog, la TotalMinutespropiedad es un doble, lo que da la cantidad total de minutos de todo el intervalo de tiempo, teniendo en cuenta todos los demás campos. Esta solución funciona de la misma manera, aunque Ticksparece un enfoque más agradable. Pero tenga en cuenta que los Ticks luego deberán transformarse en minutos si desea mostrarle al usuario alguna información que tenga sentido.
PedroC88
De acuerdo, reaccioné a la primera parte de la oración. TotalMinutes no es realmente un miembro de composición.
Henk Holterman
2

El problema aquí es que desea multiplicar el intervalo de tiempo. La solución alternativa más sencilla es utilizar ticks. p.ej.

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