How can I "pretty print" a Duration in Java?

Does anyone know of a Java library that can pretty print a number in milliseconds in the same way that C# does?

E.g., 123456 ms as a long would be printed as 4d1h3m5s.


Solution 1:

I've built a simple solution, using Java 8's Duration.toString() and a bit of regex:

public static String humanReadableFormat(Duration duration) {
    return duration.toString()
            .substring(2)
            .replaceAll("(\\d[HMS])(?!$)", "$1 ")
            .toLowerCase();
}

The result will look like:

- 5h
- 7h 15m
- 6h 50m 15s
- 2h 5s
- 0.1s

If you don't want spaces between, just remove replaceAll.

Solution 2:

Joda Time has a pretty good way to do this using a PeriodFormatterBuilder.

Quick Win: PeriodFormat.getDefault().print(duration.toPeriod());

e.g.

//import org.joda.time.format.PeriodFormatter;
//import org.joda.time.format.PeriodFormatterBuilder;
//import org.joda.time.Duration;

Duration duration = new Duration(123456); // in milliseconds
PeriodFormatter formatter = new PeriodFormatterBuilder()
     .appendDays()
     .appendSuffix("d")
     .appendHours()
     .appendSuffix("h")
     .appendMinutes()
     .appendSuffix("m")
     .appendSeconds()
     .appendSuffix("s")
     .toFormatter();
String formatted = formatter.print(duration.toPeriod());
System.out.println(formatted);

Solution 3:

Apache commons-lang provides a useful class to get this done as well DurationFormatUtils

e.g. DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) ) => 4:16:02.000 (H:m:s.millis) DurationFormatUtils.formatDurationISO( 15362 * 1000 ) ) => P0Y0M0DT4H16M2.000S, cf. ISO8601