2012-01-25 56 views
19

Me gustaría una manera elegante de redondear una Fecha de Java hacia arriba o hacia abajo al minuto más cercano (o segundo, hora, día).Java redondeo de fecha

Por ejemplo, una fecha de "mié 25 ene 10:36:34 GMT 2012" redondea al minuto más cercano sería "mié 25 ene 10:37:00 GMT 2012"

+2

JodaTime (http://joda-time.sourceforge.net/) también esto puede ser útil:? http://stackoverflow.com/a/266846/579580 – aviad

+0

JodaTime no proporciona esta función . Usar Calendar para extraer los valores del campo y luego restarlos/agregarlos era demasiado feo. – darrenmc

Respuesta

39

Si utiliza Apache commons-lang , puede use DateUtils to round your dates:

Date now = new Date(); 
Date nearestMinute = DateUtils.round(now, Calendar.MINUTE); 
+7

Cheers, truncate() también parece útil para redondear siempre – darrenmc

+0

@ guido-garcía: Ya no contiene un método 'redondo' en DateUtils. ¿Alguna alternativa en DateUtils para redondear? – hirosht

7

usted puede utilizar Apache-commons' DateUtils.

import org.apache.commons.lang.time.FastDateFormat; 
import org.apache.commons.lang.time.DateFormatUtils; 
import org.apache.commons.lang.time.DateUtils; 

FastDateFormat dtFormat = DateFormatUtils.ISO_DATETIME_FORMAT; 

Date now = new Date(); 
Date nearestHour = DateUtils.round(now, Calendar.HOUR); 
Date nearestDay = DateUtils.round(now, Calendar.DAY_OF_MONTH); 
Date nearestYear = DateUtils.round(now, Calendar.YEAR); 

System.out.println("Now: " + dtFormat.format(now)); 
System.out.println("Nearest Hour: " + dtFormat.format(nearestHour)); 
System.out.println("Nearest Day: " + dtFormat.format(nearestDay)); 
System.out.println("Nearest Year: " + dtFormat.format(nearestYear) 
20

La manera de hacerlo sin bibliotecas 3 ª parte (puede ser no tan elegante y no tan flexible, sin embargo): añadir la mitad de un campo (por un redondeo por minuto - 30 segundos) y establecer este campo y los inferiores a cero.

Calendar calendar = ... // assume you already have it with a specified Date value 

// 'add' cause changing larger fields if necessary 
calendar.add(Calendar.SECOND, 30); 
calendar.set(Calendar.SECOND, 0); 
calendar.set(Calendar.MILLISECOND, 0); 

Si el valor actual es inferior a 30 segundos, el valor de un minuto no cambiará en 'agregar'. De lo contrario, aumentará en 1. En cualquier caso, los segundos y los valores más bajos se ponen a cero. Entonces tenemos un redondeo.

+0

Gracias sí, evitar una dependencia de una biblioteca de terceros es bueno – darrenmc

3

La mejor solución es usar DateUtils de Apache commons. Sin embargo, si quiere evitar importarlos, esta sería la solución en Java. Sin embargo, no estoy seguro de si esto califica como "solución elegante".

/** 
     Takes given date and returns date rounded to nearest minute 
*/ 
public Date roundToMin(Date d){ 
    Calendar date = new GregorianCalendar(); 
    date.setTime(d); 
    int deltaMin = date.get(Calendar.SECOND)/30; 

    date.set(Calendar.SECOND, 0); 
    date.set(Calendar.MILLISECOND, 0); 
    date.add(Calendar.MINUTE, deltaMin); 

    return date.getTime(); 
} 
1

Trato de no utilizar bibliotecas adicionales si puedo lograr esto con Java claro:

new Date(((new Date().getTime() + 500)/1000) * 1000) 
+0

¿Cómo funciona esto? – Andy897

+0

@ Andy897 redondea hacia abajo (piso) si el número de millis es menor que 500 y redondea hacia arriba (techo) el número de millis es más de 500. en este ejemplo, mostré redondeo a segundos. Aunque sugeriría que es mejor usar Java 8 Time API para este –

0

Añadiendo el frasco commons-lang sólo para redondear una fecha no es una buena idea, yo prefiero este función:

public static Date round(Date d) { 
    try { 
     SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy"); 
     return sdf.parse(sdf.format(d)); 
    } catch (ParseException ex) { 
     //This exception will never be thrown, because sdf parses what it formats 
     return d; 
    } 
} 
+0

El uso más extraño del bloque try catch que he visto alguna vez: o – lmo

+0

Simple, el objeto SimpleDateFormat debe poder analizar el formato. La excepción ParseException nunca será lanzada, y es muy segura :-) –

+0

Es erróneo en mi opinión. No redondea al día más cercano sino al más cercano entre los anteriores. es decir, 09/11/2017 23:59 tu código return 09/11/2017 en vez de 10/11/2017 –