私は、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 パラメーターを受け取り、特定のタイムゾーンの特定の単位に日付を丸めることができる新しいメソッドを安全に作成できますか?