How to format an elapsed time interval in hh:mm:ss.SSS format in Java?

JDS picture JDS · Jul 15, 2011 · Viewed 40.6k times · Source

I'm making a stop watch where I'm using Java's SimpleDateFormat to convert the number of milliseconds into a nice "hh:mm:ss:SSS" format. The problem is the hours field always has some random number in it. Here's the code I'm using:

public static String formatTime(long millis) {
    SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss.SSS");

    String strDate = sdf.format(millis);
    return strDate;
}

If I take off the hh part then it works fine. Otherwise in the hh part it'll display something random like "07" even if the argument passed in (number of milliseconds) is zero.

I don't know much about the SimpleDateFormat class though. Thanks for any help.

Answer

user177800 picture user177800 · Jul 15, 2011

Support for what you want to do is built in to the latest JDKs with a little known class called TimeUnit.

What you want to use is java.util.concurrent.TimeUnit to work with intervals.

SimpleDateFormat does just what it sounds like it does, it formats instances of java.util.Date, or in your case it converts the long value into the context of a java.util.Date and it doesn't know what to do with intervals which is what you apparently are working with.

You can easily do this without having to resort to external libraries like JodaTime.

import java.util.concurrent.TimeUnit;

public class Main
{        
    private static String formatInterval(final long l)
    {
        final long hr = TimeUnit.MILLISECONDS.toHours(l);
        final long min = TimeUnit.MILLISECONDS.toMinutes(l - TimeUnit.HOURS.toMillis(hr));
        final long sec = TimeUnit.MILLISECONDS.toSeconds(l - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min));
        final long ms = TimeUnit.MILLISECONDS.toMillis(l - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min) - TimeUnit.SECONDS.toMillis(sec));
        return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
    }

    public static void main(final String[] args)
    {
        System.out.println(formatInterval(Long.parseLong(args[0])));
    }
}

The output will be formatted something like this

13:00:00.000