HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Rounding a date to a dynamic unit of time, using only JDK 6

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
jdktimeroundingdateusingdynamiconlyunit

Problem

Question originally posted on Stack Overflow here.

I'm trying to do an elegant round method that only use the JDK methods and leverage the TimeUnit class of that JDK.

/**
 * Get the date rounded to the given unit
 * @param date
 * @param unit
 * @return the rounded value
 */
public static Date round(Date date,TimeUnit unit) {
    long dateInMillies = date.getTime();
    long tzOffset = TimeZone.getDefault().getOffset(dateInMillies);
    long dateInMilliesWithoutOffset = dateInMillies + tzOffset;
    long dateInUnit = unit.convert(dateInMilliesWithoutOffset,TimeUnit.MILLISECONDS);
    long dateInMilliesRoundedWithoutOffset = unit.toMillis(dateInUnit);
    long dateInMilliesRoundedWithOffset = dateInMilliesRoundedWithoutOffset - tzOffset;
    return new Date(dateInMilliesRoundedWithOffset);
}


And my unit test is:

```
@Test
public void testRoundDate() {
Date currentDayDate = new Date();
Date currentDayBegin = DateUtils.getDayBegin(currentDayDate); // returns 00h00:00 and 000 milliseconds
Date currentDayEnd = DateUtils.getDayEnd(currentDayDate,TimeUnit.MILLISECONDS); // returns 23h59:59 and 999 milliseconds
//
final Calendar initialCalBegin = Calendar.getInstance();
initialCalBegin.setTime(currentDayBegin);
final Calendar initialCalEnd = Calendar.getInstance();
initialCalEnd.setTime(currentDayEnd);
//
Calendar testedCalendar = Calendar.getInstance();
//
testedCalendar.setTime( DateUtils.round(currentDayBegin, TimeUnit.DAYS) );
Assert.assertEquals( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalBegin.get(Calendar.DAY_OF_YEAR) );
Assert.assertEquals( testedCalendar.get(Calendar.HOUR_OF_DAY), 0 );
Assert.assertEquals( testedCalendar.get(Calendar.MINUTE), 0 );
Assert.assertEquals( testedCalendar.get(Calendar.SECOND), 0 );
Assert.assertEquals( testedCalendar.get(Calendar.MILLISECOND), 0 );
testedCalendar.setTime( DateUtils.round(currentDayEnd, TimeUnit.DAYS) );
Assert.assertEquals(

Solution

One problem you might run into is that some timezone offsets aren't integral hours. For instance, the India timezone offset is UTC +5:30. It appears that your code will probably handle this case correctly, but you probably want to add a couple unit tests to verify this.

You might also run into some problems with the Brazil time zone, since its transition between Daylight Savings Time and Standard Time happens at midnight (instead of at 2am like in most places). I've had problems trying to get the Date class to work correctly in this situation in the past. Again, I see no specific problems, but some unit tests to verify would probably be in order.

I would also suggest steering clear of the built-in Date/Calendar implementation, as there are some bugs when dealing with time zones. In my project I eventually had to use Joda under the covers and convert to/from Java Date at the API boundary. You might eventually decide that's the best solution for you, too.

Context

StackExchange Code Review Q#11997, answer score: 2

Revisions (0)

No revisions yet.