tags:

views:

14712

answers:

6

I want to record the time using System.currentTimeMillis() when a user begins something in my program. When he finishes, I will subtract the current System.currentTimeMillis() from the start variable, and I want to show them the time elapsed using a human readable format such as "XX hours, XX mins, XX seconds" or even "XX mins, XX seconds" because its not likely to take someone an hour.

What's the best way to do this?

+8  A: 

Uhm... how many milliseconds are in a second? And in a minute? Division is not that hard.

int seconds = (int) ((milliseconds / 1000) % 60);
int minutes = (int) ((milliseconds / 1000) / 60);

Continue like that for hours, days, weeks, months, year, decades, whatever.

Bombe
Actually, doing this for anything longer than an hour is not a good idea since the results could be wrong/unintuitive when daylight savings time (days of 23 or 24 hours) or leap years are involved. If I read "X will happen in 1 year/month", I'd expect it to be the same date and time.
Michael Borgwardt
System.currentTimeMillis() is immune against DST so this will not be confused by additional or missing hours. If you need to show the difference between two specific dates, you’re better off constructing Date objects with the given time and show the difference between those two.
Bombe
Beyond weeks, it is undefined, since month length is variable. So indeed, you need to compute relative to a given time reference.
PhiLho
Actually writing out the solution for hours, minutes, and seconds would be much more useful than the snarky comments.
Burly
+5  A: 

Either hand divisions, or use the SimpleDateFormat API.

long start = System.currentTimeMillis();
// do your work...
long elapsed = System.currentTimeMillis() - start;
DateFormat df = new SimpleDateFormat("HH 'hours', mm 'mins,' ss 'seconds'");
df.setTimeZone(TimeZone.getTimeZone("GMT+0"));
System.out.println(df.format(new Date(elapsed)));

Edit by Bombe: It has been shown in the comments that this approach only works for smaller durations (i.e. less than a day).

cadrian
Wow. That is an evil, timezone-dependent hack. It will break mercilessly when you have a timezone offset that is not a multiple of 60 minutes (and we have a couple of those pesky 30-minute offset timezones in the world).
Bombe
Also, it will break just as bad as soon as you include the hours in the format string and are not at GMT+0, for the same reasons.
Bombe
We do? Really? Where? Not doubting you, just never heard of it before - some new pitfall to consider ;-)
Treb
Yes. Check “List of time zones” on Wikipedia, e.g. Nepal is at GMT+05:45.
Bombe
Yeah, and Hyderabad is GMT+5.5 :\
GaZ
OK Bombe, you are right. Fixed.
cadrian
cadrian, now it will only work for durations less than a day. The number of hours will always be between 0 and 23, inclusive.
Bombe
yes, you are right.
cadrian
+1  A: 

Date Time object

PoweRoy
+4  A: 

I would not pull in the extra dependency just for that (division is not that hard, after all), but if you are using Commons Lang anyway, there are the DurationFormatUtils.

Thilo
+24  A: 

Since 1.5 there is the java.util.concurrent.TimeUnit class, use it like this:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toMinutes(millis),
    TimeUnit.MILLISECONDS.toSeconds(millis) - 
    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
siddhadev
just note on the second last line there is a minute syntax error:es(millis)),should be:es(millis))just remove the last comma.
that's freaking rad - WOOOOO!!!!
Ash Kim
A: 

DurationFormatUtils worked very nicely. Thanks, Thilo!

Udaman
Please post comments as comments by `add comment` link, not as answers :)
BalusC