2012-07-06 15 views
13

He estado buscando un mecanismo de redondeo adecuado, pero nada de lo que parece parece ser exactamente lo que necesito.DateTime Round Up and Down

Necesito redondear y redondear por separado y también tengo que dar cuenta del caso cuando ya está redondeado.

necesito el siguiente redondeo a suceder

5:00 -> RoundDown() -> 5:00 
5:04 -> RoundDown() -> 5:00 
5:09 -> RoundDown() -> 5:00 
5:10 -> RoundDown() -> 5:10 

4:00 -> RoundUp() -> 4:00 
4:50 -> RoundUp() -> 4:50 
4:51 -> RoundUp() -> 5:00 
4:56 -> RoundUp() -> 5:00 

Básicamente lo necesito al Roundup() o RoundDown() a los 10 minutos más cercanos de manera explícita, sino que también deben dejar tiempo sin tocar si ya está en un múltiplo de 10 minutos. También me gustaría para truncar cualquier segundos para que ellos no tienen ningún efecto sobre el procedimiento de redondeo

4:50:45 -> 04:50:00 -> RoundUp() -> 4:50

¿El Alguien tiene un código útil para lograr esto.

Encontré este código en alguna parte pero redondea 5:00 -> RoundUp() -> 5:10 en lugar de dejarlo intacto porque ya es un múltiplo de 10 y no necesita redondearse. Además, no estoy seguro de cómo lo afectarían los segundos

public static DateTime RoundDateTime(this DateTime dt, int minutes, RoundingDirection direction) 
{ 
    TimeSpan t; 
    switch (direction) 
    { 
     case RoundingDirection.Up: 
      t = (dt.Subtract(DateTime.MinValue)).Add(new TimeSpan(0, minutes, 0)); break; 
     case RoundingDirection.Down: 
      t = (dt.Subtract(DateTime.MinValue)); break; 
     default: 
      t = (dt.Subtract(DateTime.MinValue)).Add(new TimeSpan(0, minutes/2, 0)); break; 
    } 
    return DateTime.MinValue.Add(new TimeSpan(0, 
      (((int)t.TotalMinutes)/minutes) * minutes, 0)); 
} 

Espero que alguien pueda editar ese método para que funcione para mí. Gracias

+3

Bien. Entonces tienes código de redondeo allí. ¿Por qué no lo estás modificando para que haga lo que tienes que hacer? –

+3

¿Funcionaría? http://stackoverflow.com/questions/7029353/c-sharp-round-up-time-to-nearest-x-minutes – comecme

+0

Su regla de redondeo no está clara. Tienes alrededor de 5:09 a 5:00 pero de 4:56 a 5:00. – Rawling

Respuesta

11

¿Qué tal:

case RoundingDirection.Up: 
    t = dt.AddMinutes((60 - dt.Minute) % 10); 
case RoundingDirection.Down: 
    t = dt.AddMinutes(-dt.Minute % 10); 

Demostración: http://ideone.com/AlB7Q

+1

¿Eso se ocupa de los segundos? – comecme

+0

@comecme: Newp. – mellamokb

27

Esto le permitirá redonda de acuerdo con cualquier intervalo dado.

private static DateTime Floor(DateTime dateTime, TimeSpan interval) 
{ 
    return dateTime.AddTicks(-(dateTime.Ticks % interval.Ticks)); 
} 

private static DateTime Ceiling(DateTime dateTime, TimeSpan interval) 
{ 
    var overflow = dateTime.Ticks % interval.Ticks; 

    return overflow == 0 ? dateTime : dateTime.AddTicks(interval.Ticks - overflow); 
} 

private static DateTime Round(DateTime dateTime, TimeSpan interval) 
{ 
    var halfIntervelTicks = ((interval.Ticks + 1) >> 1); 

    return dateTime.AddTicks(halfIntervelTicks - ((dateTime.Ticks + halfIntervelTicks) % interval.Ticks)); 
} 

Para cuidar de truncar los segundos, me habría sólo hay que restar los segundos y milisegundos a partir de la fecha-hora antes de enviarlos a las funciones de redondeo.

0

Aquí es una forma rápida para truncar (redondeando hacia abajo)

var now = DateTime.Now; 
var nowTicks = now.Ticks; 

//removing the nanoseconds, miliseconds, and seconds from the nowTicks 
var lastMinute = new DateTime(nowTicks - (nowTicks % (1000*1000*10*60))); 
0

Esta función redondeará hacia arriba o hacia abajo al intervalo más próximo (minutos).

private static DateTime NormalizeReadingInterval(DateTime originalTime, int interval) 
    { 
     if (originalTime.Minute % interval == 0) return originalTime; 
     var epochTime = new DateTime(1900, 1, 1); 
     var minutes = (originalTime - epochTime).TotalMinutes; 
     var numIntervals = minutes/interval; 
     var roundedNumIntervals = Math.Round(numIntervals, 0); 
     return epochTime.AddMinutes(roundedNumIntervals * interval); 
    }