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

JavaAlgorithmDatetimeGrailsJodatime

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

Use PrettyTime for Simple Elapsed Time.

I tried HumanTime as @sfussenegger answered and using JodaTime's Period but the easiest and cleanest method for human readable elapsed time that I found was the PrettyTime library.

Here's a couple of simple examples with input and output:

Five Minutes Ago
DateTime fiveMinutesAgo = DateTime.now().minusMinutes( 5 );

new PrettyTime().format( fiveMinutesAgo.toDate() );

// Outputs: "5 minutes ago"
Awhile Ago
DateTime birthday = new DateTime(1978, 3, 26, 12, 35, 0, 0);

new PrettyTime().format( birthday.toDate() );

// Outputs: "4 decades ago"

CAUTION: I've tried playing around with the library's more precise functionality, but it produces some odd results so use it with care and in non-life threatening projects.

JP

Solution 3 - Java

You can do this with a PeriodFormatter but you don't have to go to the effort of making your own PeriodFormatBuilder as in other answers. If it suits your case, you can just use the default formatter:

Period period = new Period(startDate, endDate);
System.out.println(PeriodFormat.getDefault().print(period))

(hat tip to this answer on a similar question, I'm cross-posting for discoverability)

Solution 4 - Java

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

Solution 5 - Java

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;
} 

Solution 6 - Java

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);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionfabien7474View Question on Stackoverflow
Solution 1 - JavaBalusCView Answer on Stackoverflow
Solution 2 - JavaJoshua PinterView Answer on Stackoverflow
Solution 3 - JavasnappieTView Answer on Stackoverflow
Solution 4 - JavasfusseneggerView Answer on Stackoverflow
Solution 5 - Javajumper rbkView Answer on Stackoverflow
Solution 6 - Java4xMafoleView Answer on Stackoverflow