I have a moment duration of say 14 seconds.
const duration = moment.duration(end.diff(startTime));
If I want to display this duration as a formatted string, I can use .humanize()
duration.humanize(true)
// in a few seconds
This works fine, but is there a way for moment to format this as an exact duration like in 14 seconds
or, for a longer duration, in in 2 days and 5 hours
instead of in 2 days
?
I solved your problem with this snippet of code I made.
function formatDuration(period) {
let parts = [];
const duration = moment.duration(period);
// return nothing when the duration is falsy or not correctly parsed (P0D)
if(!duration || duration.toISOString() === "P0D") return;
if(duration.years() >= 1) {
const years = Math.floor(duration.years());
parts.push(years+" "+(years > 1 ? "years" : "year"));
}
if(duration.months() >= 1) {
const months = Math.floor(duration.months());
parts.push(months+" "+(months > 1 ? "months" : "month"));
}
if(duration.days() >= 1) {
const days = Math.floor(duration.days());
parts.push(days+" "+(days > 1 ? "days" : "day"));
}
if(duration.hours() >= 1) {
const hours = Math.floor(duration.hours());
parts.push(hours+" "+(hours > 1 ? "hours" : "hour"));
}
if(duration.minutes() >= 1) {
const minutes = Math.floor(duration.minutes());
parts.push(minutes+" "+(minutes > 1 ? "minutes" : "minute"));
}
if(duration.seconds() >= 1) {
const seconds = Math.floor(duration.seconds());
parts.push(seconds+" "+(seconds > 1 ? "seconds" : "second"));
}
return "in "+parts.join(", ");
}
This function takes a period string (ISO 8601), parses it with Moment (>2.3.0) and then, for every unit of time, pushes a string in the parts
array. Then everything inside the parts
array gets joined together with ", "
as separation string.
You can test it here: https://jsfiddle.net/mvcha2xp/6/
I'm using it as a Vue filter to humanize durations correctly.
You can customize the output of relative time functions like humanize()
using relativeTime
key of updateLocale
and relativeTimeThreshold
.
I don't know what is your expected output for a generic duration, but you can use the following code to get in 14 seconds
for a duration of 14 seconds:
const startTime = moment();
const end = moment().add(14, 'seconds');
const duration = moment.duration(end.diff(startTime));
console.log( duration.humanize(true) );
moment.relativeTimeThreshold('ss', 60);
moment.updateLocale('en', {
relativeTime : {
s: function (number, withoutSuffix, key, isFuture){
return number + ' seconds';
}
}
});
console.log( moment.duration(end.diff(startTime)).humanize(true) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
You can also take a look at this and this similar questions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With