2012-01-25 17 views
19

Vorrei un modo elegante per arrotondare una data java in su o giù al minuto più vicino (o secondo, ora, giorno).Java Data arrotondamento

Per esempio una data di "Mer 25 Gen 10:36:34 GMT 2012" arrotondato al minuto più vicino sarebbe "Mer 25 Gen 10:37:00 GMT 2012"

+2

JodaTime (http://joda-time.sourceforge.net/) anche questo può essere utile:? http://stackoverflow.com/a/266846/579580 – aviad

+0

JodaTime non fornisce questa funzionalità . Usare Calendar per estrarre i valori dei campi e quindi sottrarli/aggiungerli è troppo brutto. – darrenmc

risposta

39

Se si utilizza Apache commons-lang , è possibile use DateUtils to round your dates:

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

Cheers, truncate() sembra utile anche per arrotondare sempre verso il basso – darrenmc

+0

@ guido-garcía: Non contiene più un metodo 'round' in DateUtils. Qualche alternativa in DateUtils da arrotondare? – hirosht

7

È possibile utilizzare 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

Il modo per farlo senza librerie di terze parti (può essere non così elegante e non così flessibile, però): aggiungere una metà di un campo (per un arrotondamento per minuti - 30 secondi) e impostare questa campo e quelli più bassi a zero.

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

Se un valore corrente è inferiore a 30 secondi, un valore minuto non cambierà su "aggiungi". Altrimenti, verrà incrementato di 1. In ogni caso, i secondi ei valori più bassi vengono azzerati. Quindi abbiamo un arrotondamento.

+0

Grazie Sì, evitare una dipendenza da una libreria di terze parti è bello – darrenmc

3

La soluzione migliore è utilizzare DateUtils dai comuni Apache. Tuttavia, se si desidera evitare di importarli, questa sarebbe la soluzione in Java. Non sono sicuro se questo si qualifica come "soluzione elegante", comunque.

/** 
     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

cerco di non usare librerie aggiuntive se riesco a raggiungere questo obiettivo con Java semplice:

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

Come funziona? – Andy897

+0

@ Andy897 si sta arrotondando per difetto (piano) se il numero di millisecondi è inferiore a 500 e il numero di volte in cui il numero di millis è superiore a 500. in questo esempio ho mostrato l'arrotondamento al secondo. Anche se suggerirei che sarebbe meglio utilizzare Java 8 Time API per questo –

0

Aggiungendo il vaso commons-lang solo per arrotondare una data non è una buona idea, preferisco questo funzione:

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

Uso strano di try catch block che abbia mai visto: o – lmo

+0

Semplice, l'oggetto SimpleDateFormat deve essere in grado di analizzare ciò che formatta. La ParseException non verrà mai lanciata, la cattura è molto sicura :-) –

+0

A mio parere è sbagliato. Non si arrotonda al giorno più vicino ma al più vicino tra i precedenti. e 09/11/2017 23:59 il codice restituisce 09/11/2017 anziché il 10/11/2017 –