Calculating the difference between two Java date instances

I'm using Java's java.util.Date class in Scala and want to compare a Date object and the current time. I know I can calculate the delta by using getTime():

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

However, this just leaves me with a long representing milliseconds. Is there any simpler, nicer way to get a time delta?


The JDK Date API is horribly broken unfortunately. I recommend using Joda Time library.

Joda Time has a concept of time Interval:

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

EDIT: By the way, Joda has two concepts: Interval for representing an interval of time between two time instants (represent time between 8am and 10am), and a Duration that represents a length of time without the actual time boundaries (eg represent two hours!)

If you only care about time comparisions, most Date implementations (including the JDK one) implements Comparable interface which allows you to use the Comparable.compareTo()


Simple diff (without 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);
}

And then can you call:

getDateDiff(date1,date2,TimeUnit.MINUTES);

to get the diff of the 2 dates in minutes unit.

TimeUnit is java.util.concurrent.TimeUnit , a standard Java enum going from nanos to days.


Human readable diff (without lib)

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {
    long diffInMillies = date2.getTime() - date1.getTime();
    List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
    Collections.reverse(units);
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;
    for ( TimeUnit unit : units ) {
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;
        result.put(unit,diff);
    }
    return result;
}

http://ideone.com/5dXeu6

The output is something like Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0} , with the units ordered.

You just have to convert that map to an user-friendly string.


Warning

The above code snippets compute a simple diff between 2 instants. It can cause problems during a daylight saving switch, like explained in this post. This means if you compute the diff between dates with no time you may have a missing day/hour.

In my opinion the date diff is kind of subjective, especially on days. You may:

  • count the number of 24h elapsed time: day+1 - day = 1 day = 24h

  • count the number of elapsed time, taking care of daylight savings: day+1 - day = 1 = 24h (but using midnight time and daylight savings it could be 0 day and 23h)

  • count the number of day switches , which means day+1 1pm - day 11am = 1 day, even if the elapsed time is just 2h (or 1h if there is a daylight saving :p)

  • My answer is valid if your definition of date diff on days match the 1st case

    With JodaTime

    If you are using JodaTime you can get the diff for 2 instants (millies backed ReadableInstant) dates with:

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

    But you can also get the diff for Local dates/times:

    // 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()
    

    int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime()) 
                     / (1000 * 60 * 60 * 24) )
    

    Note that this works with UTC dates, so the difference may be a day off if you look at local dates. And getting it to work correctly with local dates requires a completely different approach due to daylight savings time.

    链接地址: http://www.djcxy.com/p/36700.html

    上一篇: Javascript中的日期差异(忽略一天中的时间)

    下一篇: 计算两个Java日期实例之间的差异