According to the example code in date-fns/date-fns#229 (comment), we can now use intervalToDuration
to convert seconds (passed as an Interval
) to a Duration
, which can then simplify formatting as desired by the OP:
import { intervalToDuration } from 'date-fns'
const seconds = 10000
intervalToDuration({ start: 0, end: seconds * 1000 })
// { hours: 2, minutes: 46, seconds: 40 }
So for the OP’s needs:
import { intervalToDuration } from 'date-fns'
const seconds = 1807
const duration = intervalToDuration({ start: 0, end: seconds * 1000 })
// { minutes: 30, seconds: 7 }
const formatted = `${duration.minutes}:${duration.seconds}`
// 30:7
Edit (2022-08-04): It was pointed out that the above simplistic code won’t 0-pad the numbers, so you will end up with 30:7
rather than 30:07
. This padding can be achieved by using String.prototype.padStart()
as follows:
import { intervalToDuration } from 'date-fns'
const seconds = 1807
const duration = intervalToDuration({ start: 0, end: seconds * 1000 })
// { minutes: 30, seconds: 7 }
const zeroPad = (num) => String(num).padStart(2, '0')
const formatted = `${zeroPad(duration.minutes)}:${zeroPad(duration.seconds)}`
// 30:07
It was also pointed out that if the Interval
goes above 60 minutes it will start incrementing the hours
within the Duration
, which the above code wouldn’t display. So here is another slightly more complex example that handles this as well as the zeroPad
case:
import { intervalToDuration } from 'date-fns'
const seconds = 1807
const duration = intervalToDuration({ start: 0, end: seconds * 1000 })
// { minutes: 30, seconds: 7 }
const zeroPad = (num) => String(num).padStart(2, '0')
const formatted = [
duration.hours,
duration.minutes,
duration.seconds,
]
.filter(Boolean)
.map(zeroPad)
.join(':')
// 30:07
There is also an issue on GitHub asking how to use a custom format with formatDuration
, which suggest that currently the only way to do so is by providing a custom Locale
. GitHub user @marselmustafin provided an example using this workaround. Following this same pattern, we could implement the OP’s desired functionality roughly as follows:
import { intervalToDuration, formatDuration } from "date-fns";
const seconds = 1807;
const duration = intervalToDuration({ start: 0, end: seconds * 1000 });
// { minutes: 30, seconds: 7 }
const zeroPad = (num) => String(num).padStart(2, "0");
const formatted = formatDuration(duration, {
format: ["minutes", "seconds"],
// format: ["hours", "minutes", "seconds"],
zero: true,
delimiter: ":",
locale: {
formatDistance: (_token, count) => zeroPad(count)
}
});
// 30:07