2012-06-27 17 views
22

¿Cómo redondear DateTime de la biblioteca Joda al X más cercano?
Por ejemplo:¿Cómo redondear DateTime of Joda library a los X minutos más cercanos?

X = 10 minutes 
Jun 27, 11:32 -> Jun 27, 11:30 
Jun 27, 11:33 -> Jun 27, 11:30 
Jun 27, 11:34 -> Jun 27, 11:30 
Jun 27, 11:35 -> Jun 27, 11:40 
Jun 27, 11:36 -> Jun 27, 11:40 
Jun 27, 11:37 -> Jun 27, 11:40 
+0

¿Su X siempre será un factor de 60? –

+0

Sí. 'X' es en realidad una fracción de hora. – Michael

+0

A partir de la hora, entonces? –

Respuesta

29

La respuesta aceptada no controla correctamente datetimes que tienen segundos o milisegundos establecidos. Para completar, aquí está una versión que manejan bien:

private DateTime roundDate(final DateTime dateTime, final int minutes) { 
    if (minutes < 1 || 60 % minutes != 0) { 
     throw new IllegalArgumentException("minutes must be a factor of 60"); 
    } 

    final DateTime hour = dateTime.hourOfDay().roundFloorCopy(); 
    final long millisSinceHour = new Duration(hour, dateTime).getMillis(); 
    final int roundedMinutes = ((int)Math.round(
     millisSinceHour/60000.0/minutes)) * minutes; 
    return hour.plusMinutes(roundedMinutes); 
} 
+1

# round * Copiar() es la forma correcta de redondear las fechas en Joda –

+4

@ MaciejŁopaciński: ¿Por qué no agrega una respuesta con esa solución? – qerub

+2

@Qerub me malentendió: la respuesta anterior está usando round * Copy() y no está marcada como respuesta a esta pregunta como debería ser. –

8

Una vez hackeado este método de hacer algo parecido. No está optimizado de ninguna manera, pero hizo lo que yo quería en ese momento. Nunca lo hice en ningún entorno de producción, y no puedo decirle nada sobre el rendimiento.

@Test 
    public void test() { 
     System.out.println(roundDate(new DateTime().withMinuteOfHour(13))); 
     System.out.println(roundDate(new DateTime().withMinuteOfHour(48))); 
     System.out.println(roundDate(new DateTime().withMinuteOfHour(0))); 
     System.out.println(roundDate(new DateTime().withMinuteOfHour(59))); 
     System.out.println(roundDate(new DateTime().withMinuteOfHour(22))); 
     System.out.println(roundDate(new DateTime().withMinuteOfHour(37))); 
    } 

    private DateTime roundDate(final DateTime dateTime) { 
     final double minuteOfHour = dateTime.getMinuteOfHour(); 
     final double tenth = minuteOfHour/10; 
     final long round = Math.round(tenth); 
     final int i = (int) (round * 10); 

     if (i == 60) { 
      return dateTime.plusHours(1).withMinuteOfHour(0); 
     } else { 
      return dateTime.withMinuteOfHour(i); 
     } 

    } 
8

Aquí hay otro enfoque que utiliza aritmética sobre el tiempo de Unix para la integridad: (. Implementado en Scala para mayor claridad)

import org.joda.time.{DateTime, Duration} 

def roundDateTime(t: DateTime, d: Duration) = { 
    t minus (t.getMillis - (t.getMillis.toDouble/d.getMillis).round * d.getMillis) 
} 

ejemplo de uso:

roundDateTime(new DateTime("2013-06-27T11:32:00"), Duration.standardMinutes(10)) 
// => 2013-06-27T11:30:00.000+02:00 

roundDateTime(new DateTime("2013-06-27T11:37:00"), Duration.standardMinutes(10)) 
// => 2013-06-27T11:40:00.000+02:00 
+16

"Implementado en Scala para mayor claridad". ROFL –

+6

Claridad como en un modelo menos moldeado, una invocación menos estática al método y menos paréntesis en este caso. :) – qerub

+2

cuanto menos diga, más claro estará –

16

Usando DateTime puro (Joda) Biblioteca de Java:

DateTime dt = new DateTime(1385577373517L, DateTimeZone.UTC); 
// Prints 2013-11-27T18:36:13.517Z 
System.out.println(dt); 

// Prints 2013-11-27T18:36:00.000Z (Floor rounded to a minute) 
System.out.println(dt.minuteOfDay().roundFloorCopy()); 

// Prints 2013-11-27T18:30:00.000Z (Rounded to custom minute Window) 
int windowMinutes = 10; 
System.out.println(
    dt.withMinuteOfHour((dt.getMinuteOfHour()/windowMinutes) * windowMinutes) 
     .minuteOfDay().roundFloorCopy() 
    ); 
+0

Esto no funciona. Todo el redondeo se está haciendo en los argumentos de la llamada withMinuteOfHour. el .minuteOfDay(). roundFloorCopy() que sigue no hace nada. –

4

Cuando se desea redondear Joda DateTime mi humilde opinión la mejor solución es utilizar el built-in roundHalfCeilingCopy y roundHalfFloorCopy métodos:

DateTime dateTime = DateTime.now(); 
DateTime newDateTime = dateTime.minuteOfHour().roundHalfCeilingCopy(); 

Tenga en cuenta que roundHalfCeilingCopy favorecerá el techo si la mitad. Puede usar roundHalfFloorCopy para favorecer el piso en caso de que esté a medio camino.

Cuestiones relacionadas