How can I "beautifully print" Duration in Java?

Does anyone know a Java library that can print numbers in milliseconds just like C # does?

For example, a length of 123456 ms will be printed as 4d1h3m5s.

+71
java date datetime time
Aug 12 '10 at 19:42
source share
11 answers

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

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

eg.

 //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); 
+86
Aug 12 '10 at 19:44
source share

I built a simple solution using Java 8 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 this:

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

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

+47
Nov 08 '16 at 12:54 on
source share

JodaTime has a Period class that can represent such values ​​and can be displayed (via IsoPeriodFormat ) in ISO8601 , e.g. PT4D1H3M5S , e.g.

 Period period = new Period(millis); String formatted = ISOPeriodFormat.standard().print(period); 

If this format is not the one you need, then PeriodFormatterBuilder allows PeriodFormatterBuilder to collect arbitrary layouts, including your C # style 4d1h3m5s .

+9
Aug 12 '10 at 19:44
source share

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

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

+9
Apr 25 '13 at 15:45
source share

With Java 8, you can also use the toString() method of java.time.Duration to format it without external libraries using an ISO 8601 second view , such as PT8H6M12.345S.

+8
Mar 20 '14 at 10:14
source share

Here's how you can do it using pure JDK code:

 import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; long diffTime = 215081000L; Duration duration = DatatypeFactory.newInstance().newDuration(diffTime); System.out.printf("%02d:%02d:%02d", duration.getDays() * 24 + duration.getHours(), duration.getMinutes(), duration.getSeconds()); 
+6
May 01 '13 at 17:29
source share

I understand that this may not be appropriate for your use case, but PrettyTime may be useful here.

 PrettyTime p = new PrettyTime(); System.out.println(p.format(new Date())); //prints: "right now" System.out.println(p.format(new Date(1000*60*10))); //prints: "10 minutes from now" 
+4
May 01 '13 at 18:11
source share

Java 9+

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

2 d 1 h 6 m 4 s

+4
Aug 08 '18 at 20:08
source share

org.threeten.extra.AmountFormats.wordBased

The ThreeTen-Extra project, which is supported by Stephen Coleborn, author of JSR 310, java.time and Joda-Time, has an AmountFormats class that works with the standard Java 8 date and time classes, although this is pretty verbose, without the possibility of 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

+4
Apr 19 '19 at 2:01
source share

An alternative to Joda-Time's construction approach will be a template solution . This is offered by my Time4J library. An example of using the Duration.Formatter class (some spaces have been added for greater readability - removing spaces will lead to the desired C # style):

 IsoUnit unit = ClockUnit.MILLIS; Duration<IsoUnit> dur = Duration.of(123456, unit).with(Duration.STD_PERIOD); String s = Duration.Formatter.ofPattern("D'd' h'h' m'm' s.fff's'").format(dur); System.out.println(s); // output: 0d 0h 2m 3.456s 

Another way is to use the net.time4j.PrettyTime class (which is also useful for localized output and relative print time):

 s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.NARROW); System.out.println(s); // output: 2m 3s 456ms 
+3
Jan 28 '15 at 14:22
source share

Java 8 version based on user678573 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 Java 8 does not have a PeriodFormatter and there are no methods like getHours, getMinutes, ...

I would be happy to see the best version for Java 8.

+2
Jun 25 '18 at 14:37
source share



All Articles