Belgor
Belgor

Reputation: 181

Moment JS duration shows wrong time?

Im trying to convert duration in seconds to human friendly output using moment js and combination of duration and format. Im getting the duration in seconds and then formatting it like so:

const value = 337650
const duration = (durationSeconds) => {
  const duration = moment.duration(durationSeconds, 'seconds')
  return moment.utc(duration.asMilliseconds()).format('D [days] HH:mm:ss')
}

console.log(`Duration: ${duration(value)}`)

outputs

"Duration: 4 days 21:47:30"

JSBin here

The problem I have is that it seems wrong. Online services like https://www.tools4noobs.com/online_tools/seconds_to_hh_mm_ss/ shows one day less. Im not sure what library/algorithm these services are using and if they are showing the correct time elapsed or moment js. Any ideas greatly appreciated!

Upvotes: 2

Views: 2693

Answers (4)

Terry Lennox
Terry Lennox

Reputation: 30725

You can use the moment-duration-format plugin to format durations, the previous approach (creating a new absolute date from a duration) is not going to work. When you add 337650 seconds to the Unix Epoch start, you get January 4, 1970, 21:47:30, which is why you're seeing the day as 4.

As a further example of how this will go badly wrong, imagine we need to format a duration of, say, 2700000 seconds. This will give us an output of "1 days 06:00:00". Why? Because it's equivalent to February 1 1970, 06:00. (The real result will be 31 days, 06:00:00).

I don't think we can blame the authors of moment.js (they've done an amazing job), it's just not using the format function on moment.js as it is supposed to be used.

By using the format function from moment-duration-format, we're formatting as a duration rather than as an absolute time and we get the right result!

momentDurationFormatSetup(moment);

const value = 337650
const duration = (durationSeconds) => {
    const duration = moment.duration(durationSeconds, 'seconds')
    return duration.format('D [days] HH:mm:ss');
}

console.log(`Duration: ${duration(value)}`)
document.getElementById('output').innerHTML = `Duration: ${duration(value)}`;
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-duration-format/2.2.2/moment-duration-format.min.js"></script>
<div id="output">
</div>

JSFiddle: https://jsfiddle.net/t07ez8o4/9/

Upvotes: 1

user3532862
user3532862

Reputation:

try something simple:

var x = 337650%86400; 
var days = (337650 - x)/86400; 
var y = x%3600; 
var hours= (x-y)/3600; 
var sec = y%60; 
var mins=(y-sec)/60; 
alert(days + ' days ' + hours+':'+mins+':'+sec)

Upvotes: 1

Sven van de Scheur
Sven van de Scheur

Reputation: 1913

Simple formatting can be done using the humanize method:

let value = 337650
let duration = moment.duration(value, 'seconds')
duration = duration.humanize()
console.log(duration)

"4 days"

Fore more sophisticated formatting you may want to dive into: https://github.com/jsmreese/moment-duration-format.

Upvotes: 1

AKX
AKX

Reputation: 169416

You seem to be converting the duration into an epoch time, then formatting it, which will be wrong.

Take a look at this Moment issue for details about duration formatting. https://github.com/moment/moment/issues/1048

Upvotes: 2

Related Questions