Full humanized durations in moment.js

2019-02-03 23:26发布

I tried this in moment.js

moment.duration(375,'days').humanize()

and get "a year" as answer, but I would expect "a year and 10 days". Is there a way in moment.js to get the full humanized value?

标签: momentjs
10条回答
劳资没心,怎么记你
2楼-- · 2019-02-03 23:31

I found this small lib, that only display duration (if you don't really need all the features of moment.js)

https://github.com/EvanHahn/HumanizeDuration.js

查看更多
Fickle 薄情
3楼-- · 2019-02-03 23:32

Use moment.relativeTimeThreshold('y', 365) to set the rounding.

moment.relativeTimeThreshold('s', 60);
moment.relativeTimeThreshold('m', 60);
moment.relativeTimeThreshold('h', 24);
moment.relativeTimeThreshold('d', 31);
moment.relativeTimeThreshold('M', 12);
moment.relativeTimeThreshold('y', 365);
查看更多
闹够了就滚
4楼-- · 2019-02-03 23:33

I was looking at the same issue and seems like there is no plan on supporting this in the future...

Although one workaround proposed is to make an language definition that overrides default implementation of humanized messages:

https://github.com/timrwood/moment/issues/348

Kind of an overkill if you ask me...

查看更多
三岁会撩人
5楼-- · 2019-02-03 23:33

Based on Ihor Kaslashnikov's solution, I modified the function to be even more accurate using vanilla Javascript.

function momentHumanize(eventDuration, unit) {
    var eventMDuration = moment.duration(eventDuration, unit);
    var eventDurationArray = [];
    if (eventMDuration.years() > 0) {
        eventDurationArray.push(eventMDuration.years() + ' years');
        eventMDuration.subtract(eventMDuration.years(), 'years')
    }
    if (eventMDuration.months() > 0) {
        eventDurationArray.push(eventMDuration.months() + ' months');
        eventMDuration.subtract(eventMDuration.months(), 'months')
    }
    if (eventMDuration.weeks() > 0) {
        eventDurationArray.push(eventMDuration.weeks() + ' weeks');
        eventMDuration.subtract(eventMDuration.weeks(), 'weeks')
    }
    if (eventMDuration.days() > 0) {
        eventDurationArray.push(eventMDuration.days() + ' days');
        eventMDuration.subtract(eventMDuration.days(), 'days')
    }
    if (eventMDuration.hours() > 0) {
        eventDurationArray.push(eventMDuration.hours() + ' hours');
        eventMDuration.subtract(eventMDuration.hours(), 'hours')
    }
    if (eventMDuration.minutes() > 0) {
        eventDurationArray.push(eventMDuration.minutes() + ' minutes');
    }
    return eventDurationArray.length === 1 ? eventDurationArray[0] : 
    eventDurationArray.join(' and ')
}

This will remove any amount from the moment instance once it humanizes it. I did this because Ihor's solution was inaccurate, given that moment's humanize function rounds the value. For example, if I had 2.8 hours, it should've been 2 hours and an hour. My solution removes the 2 hours, from the instance, leaving only 0.8 hours, and doesn't use moment's humanize function to avoid rounding.

Examples:

momentHumanize(45, 'minutes') // 45 minutes

momentHumanize(4514, 'minutes') // 3 days and 3 hours and 14 minutes

momentHumanize(45145587, 'minutes') // 85 years and 10 months and 1 days and 2 hours and 27 minutes
查看更多
欢心
6楼-- · 2019-02-03 23:42

Try this plugin:

https://github.com/jsmreese/moment-duration-format

moment.duration(123, "minutes").format("h [hrs], m [min]");
// "2 hrs, 3 min"
查看更多
叼着烟拽天下
7楼-- · 2019-02-03 23:48

i have written this javascript code to humanize the duration,

function humanizeDuration(timeInMillisecond) {
    var result = "";
    if (timeInMillisecond) {
        if ((result = Math.round(timeInMillisecond / (1000 * 60 * 60 * 24 * 30 * 12))) > 0) {//year
            result = result === 1 ? result + " Year" : result + " Years";
        } else if ((result = Math.round(timeInMillisecond / (1000 * 60 * 60 * 24 * 30))) > 0) {//months
            result = result === 1 ? result + " Month" : result + " Months";
        } else if ((result = Math.round(timeInMillisecond / (1000 * 60 * 60 * 24))) > 0) {//days
            result = result === 1 ? result + " Day" : result + " Days";
        } else if ((result = Math.round(timeInMillisecond / (1000 * 60 * 60))) > 0) {//Hours
            result = result === 1 ? result + " Hours" : result + " Hours";
        } else if ((result = Math.round(timeInMillisecond / (1000 * 60))) > 0) {//minute
            result = result === 1 ? result + " Minute" : result + " Minutes";
        } else if ((result = Math.round(timeInMillisecond / 1000)) > 0) {//second
            result = result === 1 ? result + " Second" : result + " Seconds";
        } else {
            result = timeInMillisecond + " Millisec";
        }
    }
    return result;
}
查看更多
登录 后发表回答