5

I'm trying to format a countdown timer using moment duration format but as soon as time hits below 60 minutes , the hours disappear e.g. 60 minutes display as "01:00" which is correct 59 minutes display as "59" which is not correct, it should display as "00:59"

where 3500000 milliseconds is equal to 58 minutes

I have the following code:

moment.duration(3500000).format("hh:mm", { forceLength: true })

which displays result : 58, rather than 00:58

what am I doing wrong here ?

I have also attempted the variation to no avail

moment.duration(3500000).format("HH:mm", { forceLength: true })
Danish
  • 741
  • 4
  • 17
  • 31
  • Possible duplicate of [How do I use format() on a moment.js duration?](http://stackoverflow.com/questions/13262621/how-do-i-use-format-on-a-moment-js-duration) –  Jan 03 '17 at 12:13
  • I saw that one earlier, it's an older thread at the time when duration didn't support formatting - now it does, only it's not formatting it right – Danish Jan 03 '17 at 12:16
  • For me it's an exception saying that `duration` don't have method `format` – Jyothi Babu Araja Jan 03 '17 at 12:23
  • @RC. But it gives `UTC` which in this case gives `12:58`. – Jyothi Babu Araja Jan 03 '17 at 12:26

4 Answers4

11

I can explain what's happening (I created the moment-duration-format plugin).

The forceLength option only affects the first token that has a value, meaning the first token with a value greater than 0. In your case, the hh token doesn't have a value. https://github.com/jsmreese/moment-duration-format#force-length

Switching from hh to HH means something for formatting moment objects (dates), but not for formatting moment duration objects (lengths of time) with my plugin (unless you've customized the duration formatting tokens, which is possible using my plugin).

Using moment(moment.duration(3500000)._data).format("HH:mm"); as suggested is a nice creative workaround.

If you want to grab the version of moment-duration-format that's on the repository's dev branch, there is an option that can help (see https://github.com/jsmreese/moment-duration-format/issues/22)...

In that version you can use the * character to denote the minimum token to show while trimming, even with it has no value:

moment.duration(3510000).format("*hh:mm");
--> "00:59"
moment.duration(3509999).format("*hh:mm");
--> "00:58"

Note that the default behaviour in the dev branch version changed from truncate to round so you'll drop from 00:59 to 00:58 as you pass from 58 minutes 30 seconds to 58 minutes 29 seconds. In that version you could turn on the trunc option for this output:

moment.duration(3539999).format("*hh:mm", { trunc: true });
--> "00:58"
moment.duration(3540000).format("*hh:mm", { trunc: true });
--> "00:59"

Not sure if that's what you would want for your countdown solution... maybe a feature of setting floor (trunc), ceiling, or round on the remainder would be best?

If you wanted a ceiling behaviour, you could use the dev branch version along with trunc and add 60000 to your timer value:

moment.duration(3540000 + 60000).format("*hh:mm", { trunc: true });
--> "01:00"
moment.duration(3539999 + 60000).format("*hh:mm", { trunc: true });
--> "00:59"
moment.duration(3500000 + 60000).format("*hh:mm", { trunc: true });
--> "00:59"
moment.duration(3480000 + 60000).format("*hh:mm", { trunc: true });
--> "00:59"
moment.duration(3479999 + 60000).format("*hh:mm", { trunc: true });
--> "00:58"
  • Thanks john, its a financial trading app so times have to be accurate , the solution provided here in answer only works when the duration is less than 60 minutes , on larger durations it gives out weird times - hopefully as you mentioned , we will have this feature incorporated in the future releases – Danish Jan 03 '17 at 23:12
7

Try this

moment(moment.duration(3500000)._data).format("HH:mm");
Jyothi Babu Araja
  • 10,076
  • 3
  • 31
  • 38
  • this worked, your a champion - thanks! - could you tell me where ._data comes from ? I don't see it in the documentation anywhere – Danish Jan 03 '17 at 12:26
  • 1
    @Danish `duration` object have `_data` which contains the time `object` we need for formatting. – Jyothi Babu Araja Jan 03 '17 at 12:27
  • in my opinion the forceLength option with format should have produced the desired result, rendering other non available values to 0 - perhaps missing implementation internally ? – Danish Jan 03 '17 at 12:28
  • May be we may have proper answer. Until then consider this as a workaround. :) – Jyothi Babu Araja Jan 03 '17 at 12:29
  • 2
    `moment.utc(3500000).format("HH:mm");` gives the same result without relying on any internals. Either way, the only problem is that it's only going to work up to 24 hours. – undefined Jan 10 '17 at 01:18
4

Try 'trim' parameter.

moment.duration(3500000).format("hh:mm", { trim: false })
1

My variant

moment.utc(3400000).format("HH:mm")

gives : "00:56"

Hope will be usefull.

Vladimir
  • 342
  • 1
  • 8
  • hmm.. didn't try it - might work actual implementation that I have is like moment.duration(moment(this.date).diff(moment())).format("hh:mm") so far I've done a work around where I do the provided solution by Jyothi Babu Araja, if I detect the duration to be less than 60 minutes, else I apply just normal formatting – Danish Jan 04 '17 at 01:10