225

I'd like to format a duration in seconds using a pattern like H:MM:SS. The current utilities in java are designed to format a time but not a duration.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259

22 Answers22

231

If you don't want to drag in libraries, it's simple enough to do yourself using a Formatter, or related shortcut eg. given integer number of seconds s:

  String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
Audrius Meškauskas
  • 20,936
  • 12
  • 75
  • 93
bobince
  • 528,062
  • 107
  • 651
  • 834
  • 4
    Doesn't have to be integer. If you have two dates, just plug date1.getTime() - date2.getTime() into the above equation which uses the long primitive and still works. – Josh Nov 05 '08 at 22:51
  • What if the time difference is longer than 24h? – Rajish Jul 15 '11 at 09:43
  • 2
    @Rajish: you'd have to ask the OP what they wanted in that case! Of course you can separate it out into `s/86400, (s%86400)/3600...` for days if necessary... – bobince Jul 15 '11 at 20:37
  • My solution to `s > 8640`0 (one day): `"\u221E"` - infinity – QED Aug 23 '12 at 23:21
  • If the time difference is over 24 hours, it still formats nicely the duration in hours, minutes and seconds. For my use case this is as expected. – Audrius Meškauskas Aug 29 '15 at 16:31
188

I use Apache common's DurationFormatUtils like so:

DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);
Dave Bauman
  • 9,252
  • 1
  • 19
  • 19
Gili Nachum
  • 5,288
  • 4
  • 31
  • 33
  • 21
    The easiest possible way (in apache commons style). You even have formatDurationHMS method that, you'll probably use most of the time. – Marko Mar 28 '15 at 22:06
  • 3
    Perfect! You can also add other text within apostrophe: DurationFormatUtils.formatDuration(durationInMillis, "m 'minutes' , s 'seconds'") – mihca Feb 18 '20 at 16:21
  • Unfortunately the Apache stuff isn't localized, it only supports english. – frodo2975 Dec 16 '22 at 19:06
96

If you're using a version of Java prior to 8... you can use Joda Time and PeriodFormatter. If you've really got a duration (i.e. an elapsed amount of time, with no reference to a calendar system) then you should probably be using Duration for the most part - you can then call toPeriod (specifying whatever PeriodType you want to reflect whether 25 hours becomes 1 day and 1 hour or not, etc) to get a Period which you can format.

If you're using Java 8 or later: I'd normally suggest using java.time.Duration to represent the duration. You can then call getSeconds() or the like to obtain an integer for standard string formatting as per bobince's answer if you need to - although you should be careful of the situation where the duration is negative, as you probably want a single negative sign in the output string. So something like:

public static String formatDuration(Duration duration) {
    long seconds = duration.getSeconds();
    long absSeconds = Math.abs(seconds);
    String positive = String.format(
        "%d:%02d:%02d",
        absSeconds / 3600,
        (absSeconds % 3600) / 60,
        absSeconds % 60);
    return seconds < 0 ? "-" + positive : positive;
}

Formatting this way is reasonably simple, if annoyingly manual. For parsing it becomes a harder matter in general... You could still use Joda Time even with Java 8 if you want to, of course.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Would you still recommend to use the Joda Time library when using Java 8? – Tim Büthe Aug 04 '14 at 17:20
  • 2
    @TimBüthe: No, I'd start using java.time in that case. (Although I can't immediately find an equivalent of PeriodFormatter...) – Jon Skeet Aug 04 '14 at 17:27
  • 1
    PeriodFormatter isn't included. That one of the differences between Java 8 Date Time API and Joda Time. – Tim Büthe Aug 04 '14 at 17:33
  • @TimBüthe: Right. I'd at least consider writing my own PeriodFormatter then - or possibly including Joda Time *just* for that, depending on context. – Jon Skeet Aug 04 '14 at 17:42
  • So is this where we currently stand? `java.time` is great unless you want to format durations (Really such an obscure feature?), in which case you need to have a bunch of kloogy joda-time uses? I really hope this gets addressed in something before Java-9 – Groostav Apr 13 '15 at 00:57
  • @Groostav: I think formatting a duration is *relatively* rare. An alternative to using a period text format would be to just transmit the number of nanoseconds as a number. But yes, it would be good to see this addressed in Java 9 :) – Jon Skeet Apr 13 '15 at 06:02
  • This answer is inadequate for Java 8 ("I suspect there is something somewhere"), which is now standard. The answer is thus out of date. – Rex Kerr Oct 27 '15 at 21:19
  • @RexKerr: It's not that it's out of date - it's just that as far as I can see, Java 8 doesn't provide custom period formatting. The passage of time hasn't changed that fact as far as I can see. If you *do* know of a way of formatting a period in a custom way in Java 8, please give that information. – Jon Skeet Oct 28 '15 at 07:00
  • I'm not aware of any way to do it either, and I suspect it doesn't exist (excepting using LocalTime for periods under 24 hours, which is not ideal). But neither "you can't" nor "I don't know" nor "I suspect there's something" are really a good answer to the "how do I do it" question, are they? If someone else thinks, "Oh, I'd like to format a duration as H:MM:SS!", and they read your answer, they go, "Okay, now I've got a period and...I'm stuck?!" – Rex Kerr Oct 29 '15 at 14:51
  • 1
    @RexKerr: Well, there's still "use Joda Time" if you want to, of course. Will edit again. (Looking back, I should have been recommending Duration anyway, by the sounds of it. Significant edit required...) – Jon Skeet Oct 29 '15 at 14:56
  • Easier to use the new `Math.floorMod` and `Math.floorDiv` methods instead of manual negative checking. – Mark Jeronimus May 08 '18 at 15:28
  • @MarkJeronimus: I suggest you add a new answer, as I can't immediately see how this would make it simpler. – Jon Skeet May 09 '18 at 06:12
  • My mistake. I thought I discovered something by accident when a bug in my program caused duration to be negative and then rendered. But it turned out to be rendered incorrect after all. – Mark Jeronimus May 09 '18 at 08:57
  • 8
    @MarkJeronimus Even easier would be to use the `Duration`s methods: `duration.toHours()`, `duration.toMinutesPart()` and `duration.toSecondsPart()` which are available since Java 9. And to get the absolute value one can use `duration.abs()`. – recke96 Jun 15 '18 at 17:25
  • @recke96's answer is great if you've got a code checker which considers 60/3600 magic numbers – DGK Dec 18 '19 at 13:10
  • This is a really weak answer, agree with @jonSkeet – Rob May 25 '22 at 23:25
74

This is easier since Java 9. A Duration still isn’t formattable, but methods for getting the hours, minutes and seconds are added, which makes the task somewhat more straightforward:

    LocalDateTime start = LocalDateTime.of(2019, Month.JANUARY, 17, 15, 24, 12);
    LocalDateTime end = LocalDateTime.of(2019, Month.JANUARY, 18, 15, 43, 33);
    Duration diff = Duration.between(start, end);
    String hms = String.format("%d:%02d:%02d", 
                                diff.toHours(), 
                                diff.toMinutesPart(), 
                                diff.toSecondsPart());
    System.out.println(hms);

The output from this snippet is:

24:19:21

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
30
long duration = 4 * 60 * 60 * 1000;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());
log.info("Duration: " + sdf.format(new Date(duration - TimeZone.getDefault().getRawOffset())));
Mihai Vasilache
  • 317
  • 3
  • 2
  • 14
    Hah! Just hit the wall with time zone normalization when used this method. You have to add `sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));` before using the `format` function. – Rajish Jul 15 '11 at 09:46
  • It's recommended to use `DateFormat.getDateInstance()` instead of concrete classes. – Abhijit Sarkar Jul 25 '20 at 10:58
  • 2
    This solution is fragile. It will roll over to `00:00:00.000` when the number of hours reaches 24h. Further, negative one second is formatted as `23:59:59.000`. – V.S. Aug 12 '20 at 08:00
  • I'm using: String .format("Duration %tT", duration - TimeZone.getDefault().getOffset(0)) which works well if you are fine with duration < 24 hours – Petr Nalevka Mar 14 '22 at 08:36
16

There's a fairly simple and (IMO) elegant approach, at least for durations of less than 24 hours:

DateTimeFormatter.ISO_LOCAL_TIME.format(value.addTo(LocalTime.of(0, 0)))

Formatters need a temporal object to format, so you can create one by adding the duration to a LocalTime of 00:00 (i.e. midnight). This will give you a LocalTime representing the duration from midnight to that time, which is then easy to format in standard HH:mm:ss notation. This has the advantage of not needing an external library, and uses the java.time library to do the calculation, rather than manually calculating the hours, minutes and seconds.

ctg
  • 615
  • 8
  • 16
  • 1
    good trick,. For period's of more than 24 hours, this gives you the remainder mod 24hrs, which isn't quite what I need, but I agree this is the most elegant so far. Still, I'm rather disappointed that java 8's Duration object doesn't have some built in formatting tools. – Groostav Jun 25 '21 at 23:34
12

This answer only uses Duration methods and works with Java 8 :

public static String format(Duration d) {
    long days = d.toDays();
    d = d.minusDays(days);
    long hours = d.toHours();
    d = d.minusHours(hours);
    long minutes = d.toMinutes();
    d = d.minusMinutes(minutes);
    long seconds = d.getSeconds() ;
    return 
            (days ==  0?"":days+" days,")+ 
            (hours == 0?"":hours+" hours,")+ 
            (minutes ==  0?"":minutes+" minutes,")+ 
            (seconds == 0?"":seconds+" seconds,");
}
Olivier Payen
  • 15,198
  • 7
  • 41
  • 70
lauhub
  • 894
  • 1
  • 15
  • 27
10

I'm not sure that is you want, but check this Android helper class

import android.text.format.DateUtils

For example: DateUtils.formatElapsedTime()

Sergei Maleev
  • 307
  • 3
  • 4
7

This might be kind of hacky, but it is a good solution if one is bent on accomplishing this using Java 8's java.time:

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.time.temporal.UnsupportedTemporalTypeException;

public class TemporalDuration implements TemporalAccessor {
    private static final Temporal BASE_TEMPORAL = LocalDateTime.of(0, 1, 1, 0, 0);

    private final Duration duration;
    private final Temporal temporal;

    public TemporalDuration(Duration duration) {
        this.duration = duration;
        this.temporal = duration.addTo(BASE_TEMPORAL);
    }

    @Override
    public boolean isSupported(TemporalField field) {
        if(!temporal.isSupported(field)) return false;
        long value = temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
        return value!=0L;
    }

    @Override
    public long getLong(TemporalField field) {
        if(!isSupported(field)) throw new UnsupportedTemporalTypeException(new StringBuilder().append(field.toString()).toString());
        return temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
    }

    public Duration getDuration() {
        return duration;
    }

    @Override
    public String toString() {
        return dtf.format(this);
    }

    private static final DateTimeFormatter dtf = new DateTimeFormatterBuilder()
            .optionalStart()//second
            .optionalStart()//minute
            .optionalStart()//hour
            .optionalStart()//day
            .optionalStart()//month
            .optionalStart()//year
            .appendValue(ChronoField.YEAR).appendLiteral(" Years ").optionalEnd()
            .appendValue(ChronoField.MONTH_OF_YEAR).appendLiteral(" Months ").optionalEnd()
            .appendValue(ChronoField.DAY_OF_MONTH).appendLiteral(" Days ").optionalEnd()
            .appendValue(ChronoField.HOUR_OF_DAY).appendLiteral(" Hours ").optionalEnd()
            .appendValue(ChronoField.MINUTE_OF_HOUR).appendLiteral(" Minutes ").optionalEnd()
            .appendValue(ChronoField.SECOND_OF_MINUTE).appendLiteral(" Seconds").optionalEnd()
            .toFormatter();

}
patrick
  • 194
  • 1
  • 3
  • I just tried this, and I noticed that if I called format for "hh:mm:ss" when I _didnt_ have any hours or minutes to format (eg `Duration.ofSeconds(20)`), then I'd get an `UnsupportedTemporalTypeException`). I've simply removed the code checking if the difference is `== 01`. I figured `01` was some kind of masking value that I dont complete understand, can you explain it? – Groostav Apr 13 '15 at 05:38
  • This actually worked very well. On my case I even added milliseconds... Regarding the `isSupported` method its returning the information if there is a valid field to show on the human readable string. Anyway the "masking" is actually not a mask. The code shows `return value!=0l` not `return value!=01`. Please do make use of copy-paste next time. – MrJames Nov 08 '16 at 17:13
  • 1
    The interface `TemporalAccessor` is not supposed to be misused for durations. JSR-310 has designed the interface `TemporalAmount` for this purpose. – Meno Hochschild Jan 04 '17 at 13:07
  • 2
    I recommend you always use uppercase `L` for signifying a `long` value. It’s so easy to misread lowercase `l` for digit 1, as just demonstrated. – Ole V.V. May 06 '18 at 13:58
6

Here is one more sample how to format duration. Note that this sample shows both positive and negative duration as positive duration.

import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.HOURS;
import static java.time.temporal.ChronoUnit.MINUTES;
import static java.time.temporal.ChronoUnit.SECONDS;

import java.time.Duration;

public class DurationSample {
    public static void main(String[] args) {
        //Let's say duration of 2days 3hours 12minutes and 46seconds
        Duration d = Duration.ZERO.plus(2, DAYS).plus(3, HOURS).plus(12, MINUTES).plus(46, SECONDS);

        //in case of negative duration
        if(d.isNegative()) d = d.negated();

        //format DAYS HOURS MINUTES SECONDS 
        System.out.printf("Total duration is %sdays %shrs %smin %ssec.\n", d.toDays(), d.toHours() % 24, d.toMinutes() % 60, d.getSeconds() % 60);

        //or format HOURS MINUTES SECONDS 
        System.out.printf("Or total duration is %shrs %smin %sec.\n", d.toHours(), d.toMinutes() % 60, d.getSeconds() % 60);

        //or format MINUTES SECONDS 
        System.out.printf("Or total duration is %smin %ssec.\n", d.toMinutes(), d.getSeconds() % 60);

        //or format SECONDS only 
        System.out.printf("Or total duration is %ssec.\n", d.getSeconds());
    }
}
Pavel_H
  • 358
  • 4
  • 9
6

How about the following function, which returns either +H:MM:SS or +H:MM:SS.sss

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 );
    }
}
mksteve
  • 12,614
  • 3
  • 28
  • 50
6

You can use java.time.Duration which is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementation. With Java-9 some more convenience methods were introduced.

Demo:

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Month;

public class Main {
    public static void main(String[] args) {
        LocalDateTime startDateTime = LocalDateTime.of(2020, Month.DECEMBER, 10, 15, 20, 25);
        LocalDateTime endDateTime = LocalDateTime.of(2020, Month.DECEMBER, 10, 18, 24, 30);

        Duration duration = Duration.between(startDateTime, endDateTime);
        // Default format
        System.out.println(duration);

        // Custom format
        // ####################################Java-8####################################
        String formattedElapsedTime = String.format("%02d:%02d:%02d", duration.toHours() % 24,
                duration.toMinutes() % 60, duration.toSeconds() % 60);
        System.out.println(formattedElapsedTime);
        // ##############################################################################

        // ####################################Java-9####################################
        formattedElapsedTime = String.format("%02d:%02d:%02d", duration.toHoursPart(), duration.toMinutesPart(),
                duration.toSecondsPart());
        System.out.println(formattedElapsedTime);
        // ##############################################################################
    }
}

Output:

PT3H4M5S
03:04:05
03:04:05

Learn about the modern date-time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
6

There is yet another way to make it for java8. But it works if duration is no longer than 24 hours

public String formatDuration(Duration duration) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("h:mm.SSS");
    return LocalTime.ofNanoOfDay(duration.toNanos()).format(formatter);
}
stanley
  • 119
  • 1
  • 3
  • This works nicely but what kind of magic is this? LOL Why and how this actually works? `ofNanoOfDay`, `toNanos`... and why `LocalTime`. In the context of duration this makes no sense :-\ and yet it does the trick. – t3chb0t Jan 28 '21 at 11:54
  • 1
    First vote! You made me happy today:) `Duration` needs to transform into `LocalTime` to use its `format` method. As for nanos, they were used to get number of milliseconds, but we can also write something like `LocalTime.ofSecondOfDay(duration.getSeconds()).format(formatter)` – stanley Jan 31 '21 at 15:13
  • Cool! Seconds feel more natural :-] Yeah, it's either a lot work to gain some rep here or you must be very lucky to get hundreds of votes for a question or an answer. People are pretty reluctant about voting. Sometimes in just requries a more time to someone notice your answer. Have fun and thanks again for this short solution. The other ones are so overengineered :) – t3chb0t Jan 31 '21 at 16:06
  • 2
    this is bad answer, this will fail if duration is longer than 24 hours! – Enerccio Oct 21 '21 at 08:14
4

This is a working option.

public static String showDuration(LocalTime otherTime){          
    DateTimeFormatter df = DateTimeFormatter.ISO_LOCAL_TIME;
    LocalTime now = LocalTime.now();
    System.out.println("now: " + now);
    System.out.println("otherTime: " + otherTime);
    System.out.println("otherTime: " + otherTime.format(df));

    Duration span = Duration.between(otherTime, now);
    LocalTime fTime = LocalTime.ofNanoOfDay(span.toNanos());
    String output = fTime.format(df);

    System.out.println(output);
    return output;
}

Call the method with

System.out.println(showDuration(LocalTime.of(9, 30, 0, 0)));

Produces something like:

otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463
sbclint
  • 41
  • 2
4

Here's a one-liner for converting a java.time.Duration to a nice string in Kotlin:

duration.run {
   "%d:%02d:%02d.%03d".format(toHours(), toMinutesPart(), toSecondsPart(), toMillisPart())
}

Example output: 120:56:03.004

Graham Lea
  • 5,797
  • 3
  • 40
  • 55
2
String duration(Temporal from, Temporal to) {
    final StringBuilder builder = new StringBuilder();
    for (ChronoUnit unit : new ChronoUnit[]{YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS}) {
        long amount = unit.between(from, to);
        if (amount == 0) {
            continue;
        }
        builder.append(' ')
                .append(amount)
                .append(' ')
                .append(unit.name().toLowerCase());
        from = from.plus(amount, unit);
    }
    return builder.toString().trim();
}
Bax
  • 4,260
  • 5
  • 43
  • 65
1

My library Time4J offers a pattern-based solution (similar to Apache DurationFormatUtils, but more flexible):

Duration<ClockUnit> duration =
    Duration.of(-573421, ClockUnit.SECONDS) // input in seconds only
    .with(Duration.STD_CLOCK_PERIOD); // performs normalization to h:mm:ss-structure
String fs = Duration.formatter(ClockUnit.class, "+##h:mm:ss").format(duration);
System.out.println(fs); // output => -159:17:01

This code demonstrates the capabilities to handle hour overflow and sign handling, see also the API of duration-formatter based on pattern.

Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
1

using this func

private static String strDuration(long duration) {
    int ms, s, m, h, d;
    double dec;
    double time = duration * 1.0;

    time = (time / 1000.0);
    dec = time % 1;
    time = time - dec;
    ms = (int)(dec * 1000);

    time = (time / 60.0);
    dec = time % 1;
    time = time - dec;
    s = (int)(dec * 60);

    time = (time / 60.0);
    dec = time % 1;
    time = time - dec;
    m = (int)(dec * 60);

    time = (time / 24.0);
    dec = time % 1;
    time = time - dec;
    h = (int)(dec * 24);
    
    d = (int)time;
    
    return (String.format("%d d - %02d:%02d:%02d.%03d", d, h, m, s, ms));
}
ipserc
  • 29
  • 1
  • Go to https://github.com/ipserc/duration to get a packaged version of this function – ipserc Jul 05 '20 at 14:19
  • This was the code I was looking for, the accepted answer is great, but it lacks the days, which I needed – Filnor Jul 22 '20 at 17:54
0

In scala (I saw some other attempts, and wasn't impressed):

def formatDuration(duration: Duration): String = {
  import duration._ // get access to all the members ;)
  f"$toDaysPart $toHoursPart%02d:$toMinutesPart%02d:$toSecondsPart%02d:$toMillisPart%03d"
}

Looks horrible yes? Well that's why we use IDEs to write this stuff so that the method calls ($toHoursPart etc) are a different color.

The f"..." is a printf/String.format style string interpolator (which is what allows the $ code injection to work) Given an output of 1 14:06:32.583, the f interpolated string would be equivalent to String.format("1 %02d:%02d:%02d.%03d", 14, 6, 32, 583)

Stephen
  • 19,488
  • 10
  • 62
  • 83
  • OP asked for a solution to format a duration in seconds in... **Java** – maxxyme Dec 23 '21 at 12:45
  • @maxxyme true enough. But I got to this question with a scala search term. The other scala answers (now heavily downvoted) were horrible. I wasn't about to leave those for others to find. Once somebody links here with a specific q&a (free to copy this text), then I'll remove it. Until then, it still has utility, even in the wrong place. – Stephen Feb 01 '22 at 00:21
  • 1
    @maxxyme I agree with Stephen here. Programmers of Scala, Kotlin and other JVM-based languages would often search for how to do in Java and end up here. So supplementing the Java answers with in this case a Scala answer is helpful. – Ole V.V. Apr 12 '23 at 15:05
0

Looking at all those calculations, it may is helpful that most of the Units (Hours, Minutes, etc.) have a .toFooPart() convenience method.

E.g.

Duration.ofMinutes(110L).toMinutesPart() == 50

Read: the minutes elapsed to the next value of the parent unit (Hour).

sschrass
  • 7,014
  • 6
  • 43
  • 62
-3

In Scala, building up on YourBestBet's solution but simplified:

def prettyDuration(seconds: Long): List[String] = seconds match {
  case t if t < 60      => List(s"${t} seconds")
  case t if t < 3600    => s"${t / 60} minutes" :: prettyDuration(t % 60)
  case t if t < 3600*24 => s"${t / 3600} hours" :: prettyDuration(t % 3600)
  case t                => s"${t / (3600*24)} days" :: prettyDuration(t % (3600*24))
}

val dur = prettyDuration(12345).mkString(", ") // => 3 hours, 25 minutes, 45 seconds
dpoetzsch
  • 757
  • 1
  • 7
  • 19
-4

in scala, no library needed:

def prettyDuration(str:List[String],seconds:Long):List[String]={
  seconds match {
    case t if t < 60 => str:::List(s"${t} seconds")
    case t if (t >= 60 && t< 3600 ) => List(s"${t / 60} minutes"):::prettyDuration(str, t%60)
    case t if (t >= 3600 && t< 3600*24 ) => List(s"${t / 3600} hours"):::prettyDuration(str, t%3600)
    case t if (t>= 3600*24 ) => List(s"${t / (3600*24)} days"):::prettyDuration(str, t%(3600*24))
  }
}
val dur = prettyDuration(List.empty[String], 12345).mkString("")
YourBestBet
  • 1,651
  • 1
  • 12
  • 17
  • 5
    This isn't a great advert for Scala? No library needed, but just as much code... ? – Adam Apr 23 '18 at 14:17
  • I like the recursive approach, but it can be simplified a lot: https://stackoverflow.com/a/52992235/3594403 – dpoetzsch Oct 25 '18 at 14:52