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

43,251

Solution 1

Here's how I've done it, using only the standard JDK (this will work as far back as Java 1.1 by changing StringBuilder back to StringBuffer):

static public String formatMillis(long val) {
    StringBuilder                       buf=new StringBuilder(20);
    String                              sgn="";

    if(val<0) { sgn="-"; val=Math.abs(val); }

    append(buf,sgn,0,(val/3600000)); val%=3600000;
    append(buf,":",2,(val/  60000)); val%=  60000;
    append(buf,":",2,(val/   1000)); val%=   1000;
    append(buf,".",3,(val        ));
    return buf.toString();
    }

/** Append a right-aligned and zero-padded numeric value to a `StringBuilder`. */
static private void append(StringBuilder tgt, String pfx, int dgt, long val) {
    tgt.append(pfx);
    if(dgt>1) {
        int pad=(dgt-1);
        for(long xa=val; xa>9 && pad>0; xa/=10) { pad--;           }
        for(int  xa=0;   xa<pad;        xa++  ) { tgt.append('0'); }
        }
    tgt.append(val);
    }

Solution 2

A shorter way to do this is to use the DurationFormatUtils class in Apache Commons Lang:

public static String formatTime(long millis) {
    return DurationFormatUtils.formatDuration(millis, "HH:mm:ss.S");
}

Solution 3

Why not this ?

public static String GetFormattedInterval(final long ms) {
    long millis = ms % 1000;
    long x = ms / 1000;
    long seconds = x % 60;
    x /= 60;
    long minutes = x % 60;
    x /= 60;
    long hours = x % 24;

    return String.format("%02d:%02d:%02d.%03d", hours, minutes, seconds, millis);
}

Solution 4

This is the first bit of Joda work I've done where it seemed more tedious than the JDK support. A Joda implementation for the requested format (making a few assumptions about zero fields) is:

public void printDuration(long milliSecs)
{
    PeriodFormatter formatter = new PeriodFormatterBuilder()
        .printZeroIfSupported()
        .appendHours()
        .appendSeparator(":")
        .minimumPrintedDigits(2)
        .appendMinutes()
        .appendSeparator(":")
        .appendSecondsWithMillis()
        .toFormatter();

    System.out.println(formatter.print(new Period(milliSecs)));
}

Solution 5

Reviewing the other answers, I came up with this function...

public static String formatInterval(final long interval, boolean millisecs )
{
    final long hr = TimeUnit.MILLISECONDS.toHours(interval);
    final long min = TimeUnit.MILLISECONDS.toMinutes(interval) %60;
    final long sec = TimeUnit.MILLISECONDS.toSeconds(interval) %60;
    final long ms = TimeUnit.MILLISECONDS.toMillis(interval) %1000;
    if( millisecs ) {
        return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
    } else {
        return String.format("%02d:%02d:%02d", hr, min, sec );
    }
}
Share:
43,251
JDS
Author by

JDS

Updated on October 06, 2021

Comments

  • JDS
    JDS over 2 years

    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.

  • Amir Raminfar
    Amir Raminfar almost 13 years
    Yes, this is essentially what's going.
  • Ed Staub
    Ed Staub almost 13 years
    Daylight savings, so CDT, not EDT
  • Chris
    Chris almost 13 years
    I agree, SimpleDateFormat is not designed to format elapsed time. Easier to write your own formatter or use the Joda formatter as you recommended.
  • Admin
    Admin almost 13 years
    using TimeUnit would be much cleaner in 2011.
  • Amir Raminfar
    Amir Raminfar almost 13 years
    Using JodaTime could be much cleaner in today ;)
  • Admin
    Admin over 11 years
    This is NOT the idiomatic Java way of solving this problem. SimpleDateFormat along with TimeUnit are built in to the standard library to solve these problems without including megabytes of 3rd party libraries or writing all the math and string manipulation code yourself. If for no other reason, is that SimpleDateFormat handles time zone information transparently.
  • Lawrence Dol
    Lawrence Dol over 11 years
    @Jarrod: First, for an elapsed time Timezone is irrelevant and SimpleDateFormat is not the right class, and second if you are stuck targeting an older VM TimeUnit is not an option.
  • Buffalo
    Buffalo about 6 years
    This is possible the most unreadable piece of code I've ever seen. Not talking about the complexity, just the sheer "if it compiles, it's great" attitude.
  • Lawrence Dol
    Lawrence Dol about 6 years
    @Buffalo: YETYO, but you don't know me, my mind, or my attitude.
  • Basil Bourque
    Basil Bourque over 4 years
    FYI, the Joda-Time project is now in maintenance mode, advising migration to the java.time classes. See Tutorial by Oracle.
  • bickster
    bickster over 4 years
    Best solution if you don't want your output to contain a full elapse time that could include 0s in the begining. The format I wanted was "50s ago" or "1h 2m 5s" ago. Not the full "HH:mm:ss.S" format.