## With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

No credit card required

# 1.14. Rounding Date Objects

## Problem

You need to round a date to the nearest second, minute, hour, day, month, or year.

## Solution

Use `DateUtils` to round `Date` objects to the nearest `Calendar` field. `DateUtils.round()` can round to almost every `Calendar` field, including `Calendar.SECOND`, `Calendar.MINUTE`, `Calendar.HOUR`, `Calendar.DAY_OF_MONTH`, `Calendar.MONTH`, and `Calendar.YEAR`. The following example demonstrates the use of `DateUtils.round( )`:

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

This example creates an object representing the current time and rounds this date to the nearest hour, day, and year. Assuming that the current date is March 28, 2004, and the current time is 1:48 P.M., this program creates the following output using the `FastDateFormat` class from the previous recipe:

```Now: 2004-03-28T13:48:12
Nearest Hour: 2004-03-28T14:00:00
Nearest Day: 2004-03-29T00:00:00
Nearest Year: 2004-01-01T00:00:00```

## Discussion

If you are creating a system to record the time of an event, and you are not certain exactly when that event happened, it is appropriate to round that date and time to an approximate value. Are you certain that you woke up at 9:02 A.M., 23 seconds, and 879 milliseconds? Or, is it more likely that you remember that you woke up around 9 A.M.? It would be appropriate to round this time to the `Calendar.MINUTE` or `Calendar.HOUR` field at the very least—recording a general time, such as “around 9 A.M.” In the following example, `DateUtils.round( )` calculates an approximate time:

```// Rounding to the nearest hour
Date wokeUp = new Date( );
Date wokeUpAround = DateUtils.round( now, Calendar.HOUR );```

If your `wokeUp` `Date` object is 1:31 P.M., then `wokeUpAround` will be equal to 2:00 P.M. But, if you woke up at 1:15 P.M., your `wokeUpAround` object would then be rounded down to 1:00 P.M. When you round or truncate to a field, all of the date fields less significant than the specified field are set to zero. In this example, rounding to an hour causes the minutes, seconds, and milliseconds to be set to zero. Rounding a `Date` to a `Calendar.YEAR` sets the day of the year to one and the time to the first instance of the nearest year:

```Date now = new Date( )
Date nearestYear = DateUtils.round( now, Calendar.YEAR );```

This previous code rounds to the nearest year, and if `now` is 15 May 2004, the resulting `Date` will correspond to the first instance of 2004. Alternatively, if `now` is 15 July 2004, the resulting `Date` will be the first instance of 2005.

`DateUtils.round( )` works with the following field values, listed in order of significance:

• `Calendar.MILLISECOND`

• `Calendar.SECOND`

• `Calendar.MINUTE`

• `Calendar.HOUR_OF_DAY` and `Calendar.HOUR`

• `Calendar.DATE`, `Calendar.DAY_OF_MONTH`, and `Calendar.AM_PM`

• `Calendar.MONTH`

• `DateUtils.SEMI_MONTH`

• `Calendar.YEAR`

• `Calendar.ERA`

`DateUtils` introduces a `DateUtils.SEMI_MONTH` field, which will cause dates to be rounded to the middle or beginning of a month. In `DateUtils`, the middle of the month is defined as the 15th day of the month with the second half of the month starting at midnight on the 16th day of the month:

```Calendar cal = Calendar.getInstance( );
cal.set( 2004, Calendar.MARCH, 5, 10, 2, 2 );

System.out.println( DateUtils.round( cal.getTime( ) ,
DateUtils.SEMI_MONTH ) );```

This code will print out ```Mon Mar 01 00:00:00 CST 2004``` as the 5th of March and is closer to the beginning of the month than it is to the middle of the month. If the `Calendar` object was March, 14th, 2004, and it had been rounded to a `DateUtils.SEMI_MONTH`, the rounded date would have been set to midnight on March 16th. One would think that the middle of March is the 15th? Isn’t that date the famous Ides of March—the date on which Brutus betrayed Caesar? According to `DateUtils`, the first half of the month ends at 11:59 P.M. on the 15th of the month; the `DateUtils.round( )` method returns the first instant of the beginning of the second half of March: ```March 16 12:00:00.000 A.M```.

The more you work with Java’s `Date` and `Calendar` object, the more you will curse the J2SE. If your frustration is boiling over, take a look at Joda. Joda contains an entire package devoted to date, time, and duration formatting, and it is not based on the `Date` or `Calendar` classes. For more information about Joda, take a look at the Joda project page at: http://www.joda.org/.