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

Viewed 65236

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.

12 Answers

Java 9+

Duration d1 = Duration.ofDays(0);
        d1 = d1.plusHours(47);
        d1 = d1.plusMinutes(124);
        d1 = d1.plusSeconds(124);
System.out.println(String.format("%s d %sh %sm %ss", 
                d1.toDaysPart(), 
                d1.toHoursPart(), 
                d1.toMinutesPart(), 
                d1.toSecondsPart()));

2 d 1h 6m 4s

org.threeten.extra.AmountFormats.wordBased

The ThreeTen-Extra project, which is maintained by Stephen Colebourne, the author of JSR 310, java.time, and Joda-Time, has an AmountFormats class which works with the standard Java 8 date time classes. It's fairly verbose though, with no option for more compact output.

Duration d = Duration.ofMinutes(1).plusSeconds(9).plusMillis(86);
System.out.println(AmountFormats.wordBased(d, Locale.getDefault()));

1 minute, 9 seconds and 86 milliseconds

A Java 8 version based on user678573's answer:

private static String humanReadableFormat(Duration duration) {
    return String.format("%s days and %sh %sm %ss", duration.toDays(),
            duration.toHours() - TimeUnit.DAYS.toHours(duration.toDays()),
            duration.toMinutes() - TimeUnit.HOURS.toMinutes(duration.toHours()),
            duration.getSeconds() - TimeUnit.MINUTES.toSeconds(duration.toMinutes()));
}

... since there is no PeriodFormatter in Java 8 and no methods like getHours, getMinutes, ...

I'd be happy to see a better version for Java 8.

Another Java 9+ solution:

private String formatDuration(Duration duration) {
    List<String> parts = new ArrayList<>();
    long days = duration.toDaysPart();
    if (days > 0) {
        parts.add(plural(days, "day"));
    }
    int hours = duration.toHoursPart();
    if (hours > 0 || !parts.isEmpty()) {
        parts.add(plural(hours, "hour"));
    }
    int minutes = duration.toMinutesPart();
    if (minutes > 0 || !parts.isEmpty()) {
        parts.add(plural(minutes, "minute"));
    }
    int seconds = duration.toSecondsPart();
    parts.add(plural(seconds, "second"));
    return String.join(", ", parts);
}

private String plural(long num, String unit) {
    return num + " " + unit + (num == 1 ? "" : "s");
}

E.g.,

6 days, 21 hours, 2 minutes, 14 seconds
Related