How to calculate elapsed time from now with Joda-Time?

Viewed 30990

I need to calculate the time elapsed from one specific date till now and display it with the same format as StackOverflow questions, i.e.:

15s ago
2min ago
2hours ago
2days ago
25th Dec 08

Do you know how to achieve it with the Java Joda-Time library? Is there a helper method out there that already implements it, or should I write the algorithm myself?

6 Answers

To calculate the elapsed time with JodaTime, use Period. To format the elapsed time in the desired human representation, use PeriodFormatter which you can build by PeriodFormatterBuilder.

Here's a kickoff example:

DateTime myBirthDate = new DateTime(1978, 3, 26, 12, 35, 0, 0);
DateTime now = new DateTime();
Period period = new Period(myBirthDate, now);

PeriodFormatter formatter = new PeriodFormatterBuilder()
    .appendSeconds().appendSuffix(" seconds ago\n")
    .appendMinutes().appendSuffix(" minutes ago\n")
    .appendHours().appendSuffix(" hours ago\n")
    .appendDays().appendSuffix(" days ago\n")
    .appendWeeks().appendSuffix(" weeks ago\n")
    .appendMonths().appendSuffix(" months ago\n")
    .appendYears().appendSuffix(" years ago\n")
    .printZeroNever()
    .toFormatter();

String elapsed = formatter.print(period);
System.out.println(elapsed);

This prints by now

3 seconds ago
51 minutes ago
7 hours ago
6 days ago
10 months ago
31 years ago

(Cough, old, cough) You see that I've taken months and years into account as well and configured it to omit the values when those are zero.

There is a small helper class called HumanTime that I'm pretty happy with.

This is using mysql timestamp to get elapsed time to now. Singular and plular is managed. Only display the max time.

NOTE: set your own timezone.

String getElapsedTime(String strMysqlTimestamp) {
    
    DateTimeFormatter formatter = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss.S");
    DateTime mysqlDate = formatter.parseDateTime(strMysqlTimestamp).
                         withZone(DateTimeZone.forID("Asia/Kuala_Lumpur"));
    
    DateTime now = new DateTime();
    Period period = new Period(mysqlDate, now);
    
    int seconds = period.getSeconds();
    int minutes = period.getMinutes();
    int hours = period.getHours();
    int days = period.getDays();
    int weeks = period.getWeeks();
    int months = period.getMonths();
    int years = period.getYears();
    
    String elapsedTime = "";
    if (years != 0)
        if (years == 1)
            elapsedTime = years + " year ago";
        else
            elapsedTime = years + " years ago";
    else if (months != 0)
        if (months == 1)
            elapsedTime = months + " month ago";
        else
            elapsedTime = months + " months ago";
    else if (weeks != 0)
        if (weeks == 1)
            elapsedTime = weeks + " week ago";
        else
            elapsedTime = weeks + " weeks ago";
    else if (days != 0)
        if (days == 1)
            elapsedTime = days + " day ago";
        else
            elapsedTime = days + " days ago";
    else if (hours != 0)
        if (hours == 1)
            elapsedTime = hours + " hour ago";
        else
            elapsedTime = hours + " hours ago";
    else if (minutes != 0)
        if (minutes == 1)
            elapsedTime = minutes + " minute ago";
        else
            elapsedTime = minutes + " minutes ago";
    else if (seconds != 0)
        if (seconds == 1)
            elapsedTime = seconds + " second ago";
        else
            elapsedTime = seconds + " seconds ago";   
    
    return elapsedTime;
} 

Here is my solution, using joda time.

private static final int SECOND_MILLIS = 1000;
private static final int MINUTE_MILLIS = 60 * SECOND_MILLIS;
private static final int HOUR_MILLIS = 60 * MINUTE_MILLIS;
private static final int DAY_MILLIS = 24 * HOUR_MILLIS;

public static String getTimeAgo(long time)
{
    if(time < 1000000000000L)
    {
        time *= 1000;
    }

    long now = System.currentTimeMillis();

    if(time > now || time <= 0)
    {
        return null;
    }

    final long diff = now - time;

    if(diff < MINUTE_MILLIS)
    {
        return "just now";
    }
    else if(diff < 2 * MINUTE_MILLIS)
    {
        return "a minute ago";
    }
    else if(diff < 50 * MINUTE_MILLIS)
    {
        return diff / MINUTE_MILLIS + " minutes ago";
    }
    else if(diff < 90 * MINUTE_MILLIS)
    {
        return "an hour ago";
    }
    else if(diff < 24 * HOUR_MILLIS)
    {
        return diff / HOUR_MILLIS + " hours ago";
    }
    else if(diff < 48 * HOUR_MILLIS)
    {
        return "yesterday";
    }
    else
    {
        return diff / DAY_MILLIS + " days ago";
    }
}

How to use the method:

Just call the method and pass in time in milliseconds.

For example:

long now = System.currentTimeMillis();
getTimeAgo(now);
Related