CodeReview:java日期差异(以天分辨率)

Max*_*ler 2 java datetime

请您对以下代码表示意见.

我需要计算2个Date对象之间的差异.确保两个Date对象都在同一个TimeZone中.

public class DateUtils {
public final static long DAY_TIME_IN_MILLIS = 24 * 60 * 60 * 1000;

/**
 * Compare between 2 dates in day resolution.
 * 
 * @return positive integer if date1 > date2, negative if date1 < date2. 0 if they are equal.
 */
public static int datesDiffInDays(final Date date1, final Date date2){
    long date1DaysMS = date1.getTime() - (date1.getTime() % DAY_TIME_IN_MILLIS);
    long date2DaysMS = date2.getTime() - (date2.getTime() % DAY_TIME_IN_MILLIS);

    long timeInMillisDiff = (date1DaysMS - date2DaysMS);
    int ret = (int) (timeInMillisDiff / DAY_TIME_IN_MILLIS); 
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

你能指出一个我可能错过的问题吗?

编辑:@mmyers问我是否通过了我的单元测试.嗯,是.但我没有真正的约会经验,我知道这是一个很大的主题.发布在我正在使用的单元测试下面.

public class TestMLDateUtils {

@Test
public final void testDatesDiffInDays() {
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

    // 00:00:00.000 1.1.1970
    Calendar cal1970 = Calendar.getInstance();
    cal1970.setTimeInMillis(0);

    Calendar tested = Calendar.getInstance();
    tested.setTimeInMillis(0);

    // Add 1 millisecond, date = 00:00:00.001 1.1.1970
    tested.add(Calendar.MILLISECOND, 1);

    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == 0);

    // Add 1 second, date = 00:00:01.001 1.1.1970
    tested.add(Calendar.SECOND, 1);
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == 0);

    // Add 1 minute, date = 00:01:01.001 1.1.1970
    tested.add(Calendar.MINUTE, 1);
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == 0);

    // Add 1 hour, date = 01:01:01.001 1.1.1970
    tested.add(Calendar.HOUR_OF_DAY, 1);
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == 0);

    // date = 23:59:59.999 1.1.1970
    tested.setTimeInMillis(0);
    tested.add(Calendar.MILLISECOND, 999);
    tested.add(Calendar.SECOND, 59);
    tested.add(Calendar.MINUTE, 59);
    tested.add(Calendar.HOUR_OF_DAY, 23);
    //System.out.println("D: " + tested.getTime());
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == 0);

    // date = 00:00:00.000 2.1.1970
    tested.setTimeInMillis(0);
    tested.add(Calendar.DAY_OF_MONTH, 1);
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == -1);
    assertTrue(DateUtils.datesDiffInDays(tested.getTime(), cal1970.getTime()) == 1);

    // date = 00:00:00.001 2.1.1970
    tested.add(Calendar.MILLISECOND, 1);
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == -1);
    assertTrue(DateUtils.datesDiffInDays(tested.getTime(), cal1970.getTime()) == 1);

    // date = 00:00:01.001 2.1.1970
    tested.add(Calendar.SECOND, 1);
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == -1);
    assertTrue(DateUtils.datesDiffInDays(tested.getTime(), cal1970.getTime()) == 1);

    // date = 00:01:01.001 2.1.1970
    tested.add(Calendar.MINUTE, 1);
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == -1);
    assertTrue(DateUtils.datesDiffInDays(tested.getTime(), cal1970.getTime()) == 1);

    // date = 01:01:01.001 2.1.1970
    tested.add(Calendar.HOUR_OF_DAY, 1);
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == -1);
    assertTrue(DateUtils.datesDiffInDays(tested.getTime(), cal1970.getTime()) == 1);

    // date = 13:01:01.001 2.1.1970
    tested.add(Calendar.HOUR_OF_DAY, 12);
    assertTrue(DateUtils.datesDiffInDays(cal1970.getTime(), tested.getTime()) == -1);
    assertTrue(DateUtils.datesDiffInDays(tested.getTime(), cal1970.getTime()) == 1);
}
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 8

  • 即时问题:由于夏令时变化,天数可能少于或超过24小时.

  • 次要问题:通常当人们在几天内思考时,他们的确意味着"人类的日子",而不是"24小时的时期".换句话说,很多人会说第二天晚上7点到7点是一天的差异,而同一天早上7点到晚上7点是零天的差异.两者都是12个小时.此时,您确实需要知道正在考虑的日历.

当然,这对你的情况可能无关紧要,但我们真的不知道那是什么.

  • 第三个问题:您使用的是内置日历API而不是Joda Time.这几乎从来都不是一个好主意 - 它是可怕的,充满了陷阱和问题.是的,这里的常客会告诉你,当涉及到Java日期和时间时,这总是我答案的一部分 - 并且有充分的理由.这真的很重要.

编辑:您的测试将默认时区设置为UTC.这不是一个好主意(特别是没有在finally语句中重置它).时区很棘手,但你应该考虑一下你有什么价值,它们意味着什么,以及涉及的时区.