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