title: Most elegant way to round a date to a dynamic unit of time, using only JDK 6
body: <p>I'm trying to do an elegant round method that only use the JDK methods and leverage the TimeUnit class of that JDK.</p>
  
  <p>I've made the following code:</p>
  
  <pre><code>   /**
       * 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);
      }
  </code></pre>
  
  <p>And my unit test is:</p>
  
  <pre><code>@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( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalEnd.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(currentDayBegin, TimeUnit.HOURS) );
          Assert.assertEquals( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalBegin.get(Calendar.DAY_OF_YEAR) );
          Assert.assertEquals( testedCalendar.get(Calendar.HOUR_OF_DAY), initialCalBegin.get(Calendar.HOUR_OF_DAY) );
          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.HOURS) );
          Assert.assertEquals( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalEnd.get(Calendar.DAY_OF_YEAR) );
          Assert.assertEquals( testedCalendar.get(Calendar.HOUR_OF_DAY), initialCalEnd.get(Calendar.HOUR_OF_DAY) );
          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(currentDayBegin, TimeUnit.MINUTES) );
          Assert.assertEquals( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalBegin.get(Calendar.DAY_OF_YEAR) );
          Assert.assertEquals( testedCalendar.get(Calendar.HOUR_OF_DAY), initialCalBegin.get(Calendar.HOUR_OF_DAY) );
          Assert.assertEquals( testedCalendar.get(Calendar.MINUTE), initialCalBegin.get(Calendar.MINUTE) );
          Assert.assertEquals( testedCalendar.get(Calendar.SECOND), 0 );
          Assert.assertEquals( testedCalendar.get(Calendar.MILLISECOND), 0 );
          testedCalendar.setTime( DateUtils.round(currentDayEnd, TimeUnit.MINUTES) );
          Assert.assertEquals( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalEnd.get(Calendar.DAY_OF_YEAR) );
          Assert.assertEquals( testedCalendar.get(Calendar.HOUR_OF_DAY), initialCalEnd.get(Calendar.HOUR_OF_DAY) );
          Assert.assertEquals( testedCalendar.get(Calendar.MINUTE), initialCalEnd.get(Calendar.MINUTE) );
          Assert.assertEquals( testedCalendar.get(Calendar.SECOND), 0 );
          Assert.assertEquals( testedCalendar.get(Calendar.MILLISECOND), 0 );
          //
          testedCalendar.setTime( DateUtils.round(currentDayBegin, TimeUnit.SECONDS) );
          Assert.assertEquals( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalBegin.get(Calendar.DAY_OF_YEAR) );
          Assert.assertEquals( testedCalendar.get(Calendar.HOUR_OF_DAY), initialCalBegin.get(Calendar.HOUR_OF_DAY) );
          Assert.assertEquals( testedCalendar.get(Calendar.MINUTE), initialCalBegin.get(Calendar.MINUTE) );
          Assert.assertEquals( testedCalendar.get(Calendar.SECOND), initialCalBegin.get(Calendar.SECOND) );
          Assert.assertEquals( testedCalendar.get(Calendar.MILLISECOND), 0 );
          testedCalendar.setTime( DateUtils.round(currentDayEnd, TimeUnit.SECONDS) );
          Assert.assertEquals( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalEnd.get(Calendar.DAY_OF_YEAR) );
          Assert.assertEquals( testedCalendar.get(Calendar.HOUR_OF_DAY), initialCalEnd.get(Calendar.HOUR_OF_DAY) );
          Assert.assertEquals( testedCalendar.get(Calendar.MINUTE), initialCalEnd.get(Calendar.MINUTE) );
          Assert.assertEquals( testedCalendar.get(Calendar.SECOND), initialCalEnd.get(Calendar.SECOND) );
          Assert.assertEquals( testedCalendar.get(Calendar.MILLISECOND), 0 );
          //
          testedCalendar.setTime( DateUtils.round(currentDayBegin, TimeUnit.MILLISECONDS) );
          Assert.assertEquals( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalBegin.get(Calendar.DAY_OF_YEAR) );
          Assert.assertEquals( testedCalendar.get(Calendar.HOUR_OF_DAY), initialCalBegin.get(Calendar.HOUR_OF_DAY) );
          Assert.assertEquals( testedCalendar.get(Calendar.MINUTE), initialCalBegin.get(Calendar.MINUTE) );
          Assert.assertEquals( testedCalendar.get(Calendar.SECOND), initialCalBegin.get(Calendar.SECOND) );
          Assert.assertEquals( testedCalendar.get(Calendar.MILLISECOND), initialCalBegin.get(Calendar.MILLISECOND) );
          testedCalendar.setTime( DateUtils.round(currentDayEnd, TimeUnit.MILLISECONDS) );
          Assert.assertEquals( testedCalendar.get(Calendar.DAY_OF_YEAR), initialCalEnd.get(Calendar.DAY_OF_YEAR) );
          Assert.assertEquals( testedCalendar.get(Calendar.HOUR_OF_DAY), initialCalEnd.get(Calendar.HOUR_OF_DAY) );
          Assert.assertEquals( testedCalendar.get(Calendar.MINUTE), initialCalEnd.get(Calendar.MINUTE) );
          Assert.assertEquals( testedCalendar.get(Calendar.SECOND), initialCalEnd.get(Calendar.SECOND) );
          Assert.assertEquals( testedCalendar.get(Calendar.MILLISECOND), initialCalEnd.get(Calendar.MILLISECOND) );
          ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          // The TimeUnits under the millisecond precision should not procude any change to the date
          Assert.assertEquals(DateUtils.round(currentDayBegin, TimeUnit.MICROSECONDS) , currentDayBegin);
          Assert.assertEquals(DateUtils.round(currentDayEnd, TimeUnit.MICROSECONDS) , currentDayEnd);
          Assert.assertEquals(DateUtils.round(currentDayDate, TimeUnit.MICROSECONDS) , currentDayDate);
          //
          Assert.assertEquals(DateUtils.round(currentDayBegin, TimeUnit.NANOSECONDS) , currentDayBegin);
          Assert.assertEquals(DateUtils.round(currentDayEnd, TimeUnit.NANOSECONDS) , currentDayEnd);
          Assert.assertEquals(DateUtils.round(currentDayDate, TimeUnit.NANOSECONDS) , currentDayDate);
      }
  </code></pre>
  
  <p>It seems what i've done works fine and is quite elegant.
  However i'm not used to use timezones, and i wonder if this code works fine on very specific cases.
  For exemple, do you see something that could happen a given day, for a country that has an offset change in its timezone?
  Please tell me if you think something in wrong in my code.</p>
  
  <p>Can i safely create a new method that takes a TimeZone parameter and can thus round a date to a given unit on a given timezone?</p>