Moment JS duration humanize more precise

moment duration
moment-duration-format is not a function
moment js cdn
moment isafter
moment add days
moment compare dates
moment start of day

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()

// 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?

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=""></script>

Feature request: A more accurate .humanize · Issue #348 · moment , Support locale/humanize jsmreese/moment-duration-format#16 think it would be nice for Moment's humanize to be (optionally) more precise,  MomentJS - Durations - MomentJS provides an important feature called durations which handles length of time for given units. In this chapter, you will learn this in detail.

No. The only argument that .humanize() takes is the suffix toggle. If you check the source for the internal function that the humanize method uses, you can see that it always rounds the durations. If you want more specificity, you'll need to implement your own method with the desired behavior.

Humanize, If you want an oriented duration in a month , a month ago (with suffix), pass in true as seen below. moment.duration(1, "minutes").humanize(true); // in a minute. moment-indefinite-precision This is a plugin for the moment.js JavaScript library, to display durations more precisely than.humanize does, and still in a human-readable format. Moment contains some support for formatting durations, however it performs a lot of 'rounding' on the result and yields only an approximate description.

Possible solution is to use another library, which does this as OP stated.

humanizeDuration(3000)      // '3 seconds'
humanizeDuration(2250)      // '2.25 seconds'
humanizeDuration(97320000)  // '1 day, 3 hours, 2 minutes'

Docs, humanize-duration. 3.23.1 • Public • Published Install. npm i humanize-​duration Homepage.  moment-precise-range This is a plugin for the moment.js JavaScript library, to display date/time ranges precisely, in a human-readable format. Moment already contains some support for formatting date/time ranges, however it performs a lot of 'rounding' on the result and yields only an approximate description.

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:

I'm using it as a Vue filter to humanize durations correctly.

humanize-duration, Learn about our RFC process, Open RFC meetings & more. The fallback number format function output can be localized using options detailed at the moment-duration-format and its fallback number formatting function do  @FGRibreau, this issue came up in #232, and the OP over there seemed to be OK not adding that to core.. You could write a language definition called precise-english or something for when you want to more precise relative times.

moment-duration-format, Moment JS duration humanize more precise. moment duration moment-duration-​format is not a function moment js cdn moment isafter moment#isbefore // 1:30 duration.humanize() 2 hour duration.humanize({precision: 2}) 1 hour 30 minutes duration.humanize({precision: 3}) 1 hour 30 minutes 0 seconds The second problem is when there is the number 0. Momentjs translates it as "few seconds". I'm not so sure how it could be achieved but it would be cool to have some kind of formatting.

Moment JS duration humanize more precise, MomentJS - Durations - MomentJS provides an important feature called durations which moment.duration(Number, String); moment.duration().​humanize();. Moment.js also has duration objects. Where a moment is defined as a single point in time, a duration is defined as a length of time. Durations do not have a defined beginning and end date. They are contextless. A duration is conceptually more similar to '2 hours' than to 'between 2 and 4 pm today'.

MomentJS - Durations, A moment.js plugin to display human-readable date/time ranges. Most Recent Commit HH:mm:ss'); var m2 = moment('2014-02-03 15:04:05','YYYY-MM-DD HH:mm:ss'); var diff = moment.duration(m1.diff(m2)).humanize(); // 'a month'. If you are wanting to set the offset globally, try using moment-timezone. Note that once you set an offset, it's fixed and won't change on its own (i.e there are no DST rules). If you want an actual time zone -- time in a particular location, like America/Los_Angeles, consider moment-timezone. moment().utcOffset(120);