我正在尝试做一个优雅的圆形方法,它只使用 JDK 方法并利用该 JDK 的 TimeUnit 类。
我制作了以下代码:
/**
* 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);
}
我的单元测试是:
@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);
}
看来我所做的工作很好,而且非常优雅。但是我不习惯使用时区,我想知道这段代码在非常特殊的情况下是否可以正常工作。例如,对于一个时区发生偏移变化的国家/地区,您是否看到某一天可能发生的事情?如果您认为我的代码有问题,请告诉我。
我可以安全地创建一个采用 TimeZone 参数的新方法,从而可以将日期舍入到给定时区的给定单位吗?