2

我正在尝试做一个优雅的圆形方法,它只使用 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 参数的新方法,从而可以将日期舍入到给定时区的给定单位吗?

4

0 回答 0