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

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

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


当前回答

在java中有一个简单的方法来做到这一点

//创建一个实用方法

public long getDaysBetweenDates(Date d1, Date d2){
return TimeUnit.MILLISECONDS.toDays(d1.getTime() - d2.getTime());
}

该方法将返回两个日期之间的天数。您可以使用默认的java日期格式,也可以轻松地从任何日期格式转换。

其他回答

因为您正在使用Scala,所以有一个非常好的Scala库Lamma。在南丫岛,你可以直接用-运算符减去日期

scala> Date(2015, 5, 5) - 2     // minus days by int
res1: io.lamma.Date = Date(2015,5,3)

scala> Date(2015, 5, 15) - Date(2015, 5, 8)   // minus two days => difference between two days
res2: Int = 7

只需要对每个函数调用getTime,取其差值,然后除以一天中的毫秒数。

简单的diff(不含lib)

/**
 * Get a diff between two dates
 * @param date1 the oldest date
 * @param date2 the newest date
 * @param timeUnit the unit in which you want the diff
 * @return the diff value, in the provided unit
 */
public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {
    long diffInMillies = date2.getTime() - date1.getTime();
    return timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
}

然后你可以调用:

getDateDiff(date1,date2,TimeUnit.MINUTES);

以分钟为单位获取两个日期的差值。

TimeUnit是java.util.concurrent。TimeUnit,一个从纳米到天的标准Java枚举。


人类可读的差异(不含lib)

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {

    long diffInMillies = date2.getTime() - date1.getTime();

    //create the list
    List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
    Collections.reverse(units);

    //create the result map of TimeUnit and difference
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;

    for ( TimeUnit unit : units ) {
        
        //calculate difference in millisecond 
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;

        //put the result in the map
        result.put(unit,diff);
    }

    return result;
}

http://ideone.com/5dXeu6

输出类似Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0},单位是有序的。

您只需将该映射转换为用户友好的字符串。


警告

上面的代码段计算两个瞬间之间的简单差。它会在夏令时切换期间导致问题,就像这篇文章中解释的那样。这意味着如果你计算没有时间的日期之间的差异,你可能会少了一天/小时。

在我看来,日期的差异是主观的,尤其是在日子上。你可以:

计算经过24小时的时间:day+1 - day = 1 day = 24h 计算经过的时间,考虑到夏令时:天+1 -天= 1 = 24小时(但使用午夜时间和夏令时,它可以是0天和23小时) 计算日开关的数量,这意味着一天+1 1pm -一天11am = 1天,即使经过的时间只有2h(如果有夏令时则为1h:p)

我的答案是有效的,如果你的日期差异的定义天匹配第一种情况

与JodaTime

如果你正在使用JodaTime,你可以得到2个瞬间的差异(millies支持ReadableInstant)日期:

Interval interval = new Interval(oldInstant, new Instant());

但是你也可以得到本地日期/时间的差异:

// returns 4 because of the leap year of 366 days
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5), PeriodType.years()).getYears() 

// this time it returns 5
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5+1), PeriodType.years()).getYears() 

// And you can also use these static methods
Years.yearsBetween(LocalDate.now(), LocalDate.now().plusDays(365*5)).getYears()

如果你用d1和d2作为日期,最好的解决方案可能是这样的:

int days1 = d1.getTime()/(60*60*24*1000);//find the number of days since the epoch.
int days2 = d2.getTime()/(60*60*24*1000);

然后说

days2-days1

或者其他

在阅读了许多关于这个问题的回答和评论后,我的印象是,要么使用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);

}