How to format an elapsed time interval in hh:mm:ss.SSS format in Java?
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 );
}
}
JDS
Updated on October 06, 2021Comments
-
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 almost 13 yearsYes, this is essentially what's going.
-
Ed Staub almost 13 yearsDaylight savings, so CDT, not EDT
-
Chris almost 13 yearsI agree, SimpleDateFormat is not designed to format elapsed time. Easier to write your own formatter or use the Joda formatter as you recommended.
-
Admin almost 13 yearsusing
TimeUnit
would be much cleaner in 2011. -
Amir Raminfar almost 13 yearsUsing JodaTime could be much cleaner in today ;)
-
Admin over 11 yearsThis is NOT the idiomatic Java way of solving this problem.
SimpleDateFormat
along withTimeUnit
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 thatSimpleDateFormat
handles time zone information transparently. -
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 about 6 yearsThis 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 about 6 years@Buffalo: YETYO, but you don't know me, my mind, or my attitude.
-
Basil Bourque over 4 yearsFYI, the Joda-Time project is now in maintenance mode, advising migration to the java.time classes. See Tutorial by Oracle.
-
bickster over 4 yearsBest 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.