我在Scala中使用Java的Java .util.Date类,并希望比较Date对象和当前时间。我知道我可以通过使用getTime()来计算delta:

(new java.util.Date()).getTime() - oldDate.getTime()

然而,这只给我留下一个长表示毫秒。有没有更简单,更好的方法来得到时间?


当前回答

在阅读了许多关于这个问题的回答和评论后,我的印象是,要么使用Joda时间,要么考虑到日光节约时间的一些特点等等。由于这两种方法我都不想做,所以我最终编写了几行代码来计算两个日期之间的差异,而没有使用任何与日期或时间相关的Java类。

在下面的代码中,年、月和日的数字与现实生活中的数字相同。例如,2015年12月24日,年= 2015,月= 12,日= 24。

我想分享这些代码,以防其他人想要使用它。有3种方法:1)找出给定年份是否是闰年的方法2)计算给定年份1月1日的天数的方法3)计算任意两个日期之间天数的方法2(结束日期减去开始日期)。

方法如下:

1)

public static boolean isLeapYear (int year) {
    //Every 4. year is a leap year, except if the year is divisible by 100 and not by 400
    //For example 1900 is not a leap year but 2000 is

    boolean result = false;

    if (year % 4 == 0) {
        result = true;
    }
    if (year % 100 == 0) {
        result = false;
    }
    if (year % 400 == 0) {
        result = true;
    }

    return result;

}

2)

public static int daysGoneSince (int yearZero, int year, int month, int day) {
    //Calculates the day number of the given date; day 1 = January 1st in the yearZero

    //Validate the input
    if (year < yearZero || month < 1 || month > 12 || day < 1 || day > 31) {
        //Throw an exception
        throw new IllegalArgumentException("Too many or too few days in month or months in year or the year is smaller than year zero");
    }
    else if (month == 4 || month == 6 || month == 9 || month == 11) {//Months with 30 days
        if (day == 31) {
            //Throw an exception
            throw new IllegalArgumentException("Too many days in month");
        }
    }
    else if (month == 2) {//February 28 or 29
        if (isLeapYear(year)) {
            if (day > 29) {
                //Throw an exception
                throw new IllegalArgumentException("Too many days in month");
            }
        }
        else if (day > 28) {
            //Throw an exception
            throw new IllegalArgumentException("Too many days in month");
        }
    }

    //Start counting days
    int days = 0;

    //Days in the target month until the target day
    days = days + day;

    //Days in the earlier months in the target year
    for (int i = 1; i < month; i++) {
        switch (i) {
            case 1: case 3: case 5:
            case 7: case 8: case 10:
            case 12:
                days = days + 31;
                break;
            case 2:
                days = days + 28;
                if (isLeapYear(year)) {
                    days = days + 1;
                }
                break;
            case 4: case 6: case 9: case 11:
                days = days + 30;
                break;
        }
    }

    //Days in the earlier years
    for (int i = yearZero; i < year; i++) {
        days = days + 365;
        if (isLeapYear(i)) {
            days = days + 1;
        }
    }

    return days;

}

3)

public static int dateDiff (int startYear, int startMonth, int startDay, int endYear, int endMonth, int endDay) {

    int yearZero;

    //daysGoneSince presupposes that the first argument be smaller or equal to the second argument
    if (10000 * startYear + 100 * startMonth + startDay > 10000 * endYear + 100 * endMonth + endDay) {//If the end date is earlier than the start date
        yearZero = endYear;
    }
    else {
        yearZero = startYear;
    }

    return daysGoneSince(yearZero, endYear, endMonth, endDay) - daysGoneSince(yearZero, startYear, startMonth, startDay);

}

其他回答

以毫秒为单位减去日期是可行的(如另一篇文章所述),但在清除日期的时间部分时,你必须使用HOUR_OF_DAY而不是HOUR:

public static final long MSPERDAY = 60 * 60 * 24 * 1000;
...
final Calendar dateStartCal = Calendar.getInstance();
dateStartCal.setTime(dateStart);
dateStartCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateStartCal.set(Calendar.MINUTE, 0);
dateStartCal.set(Calendar.SECOND, 0);
dateStartCal.set(Calendar.MILLISECOND, 0);
final Calendar dateEndCal = Calendar.getInstance();
dateEndCal.setTime(dateEnd);
dateEndCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateEndCal.set(Calendar.MINUTE, 0);
dateEndCal.set(Calendar.SECOND, 0);
dateEndCal.set(Calendar.MILLISECOND, 0);
final long dateDifferenceInDays = ( dateStartCal.getTimeInMillis()
                                  - dateEndCal.getTimeInMillis()
                                  ) / MSPERDAY;
if (dateDifferenceInDays > 15) {
    // Do something if difference > 15 days
}

注意:startDate和endDates为-> java.util.Date

import org.joda.time.Duration;
import org.joda.time.Interval;
// Use .getTime() unless it is a joda DateTime object
Interval interval = new Interval(startDate.getTime(), endDate.getTime());
Duration period = interval.toDuration();
//gives the number of days elapsed between start and end date.
period.getStandardDays();

与天类似,你也可以得到小时、分钟和秒

period.getStandardHours();
period.getStandardMinutes();
period.getStandardSeconds();
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();

https://www.joda.org/joda-time/faq.html#datediff

只需在两个Date对象上使用下面的方法。如果你想传递当前日期,只需传递new date()作为第二个参数,因为它是用当前时间初始化的。

public String getDateDiffString(Date dateOne, Date dateTwo)
{
    long timeOne = dateOne.getTime();
    long timeTwo = dateTwo.getTime();
    long oneDay = 1000 * 60 * 60 * 24;
    long delta = (timeTwo - timeOne) / oneDay;

    if (delta > 0) {
        return "dateTwo is " + delta + " days after dateOne";
    }
    else {
        delta *= -1;
        return "dateTwo is " + delta + " days before dateOne";
     }
}

此外,除了从天数,如果,你也想要其他参数的差异,使用下面的片段,

int year = delta / 365;
int rest = delta % 365;
int month = rest / 30;
rest = rest % 30;
int weeks = rest / 7;
int days = rest % 7;

p.s. Code完全取自SO答案。

一个稍微简单一点的选择:

System.currentTimeMillis() - oldDate.getTime()

至于“更好”,你到底需要什么?将时间持续时间表示为小时数和天数等的问题是,由于日期的复杂性,它可能导致不准确和错误的期望(例如,由于夏令时,一天可能有23或25小时)。