36

I have an ISO 8601 formatted duration, for eg: PT5M or PT120S.

Is there any way I can parse these using moment.js and fetch the number of minutes specified in the duration?

Thank you!

PS: I looked at Parse ISO 8601 durations and Convert ISO 8601 time format into normal time duration

but was keen to know if this was do-able with moment.

Community
  • 1
  • 1
Qrious
  • 677
  • 2
  • 9
  • 15
  • Did you check their documentation? I don't see ISO8601 duration parsing there http://momentjs.com/docs/#/parsing/ – Xotic750 Jan 09 '15 at 00:17

3 Answers3

56

moment does parse ISO-formatted durations out of the box with the moment.duration method:

moment.duration('P1Y2M3DT4H5M6S')

The regex is gnarly, but supports a number of edge cases and is pretty thoroughly tested.

Codebling
  • 10,764
  • 2
  • 38
  • 66
bollwyvl
  • 1,231
  • 11
  • 6
8

It doesn't appear to be one of the supported formats: http://momentjs.com/docs/#/durations/

There aren't any shortage of github repos that solve it with regex (as you saw, based on the links you provided). This solves it without using Date. Is there even a need for moment?

var regex = /P((([0-9]*\.?[0-9]*)Y)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)W)?(([0-9]*\.?[0-9]*)D)?)?(T(([0-9]*\.?[0-9]*)H)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)S)?)?/

minutesFromIsoDuration = function(duration) {
    var matches = duration.match(regex);

    return parseFloat(matches[14]) || 0;
}

If you test it:

minutesFromIsoDuration("PT120S");

0

minutesFromIsoDuration("PT5M");

5

If you want the logical duration in minutes, you might get away with:

return moment.duration({
    years: parseFloat(matches[3]),
    months: parseFloat(matches[5]),
    weeks: parseFloat(matches[7]),
    days: parseFloat(matches[9]),
    hours: parseFloat(matches[12]),
    minutes: parseFloat(matches[14]),
    seconds: parseFloat(matches[16])
});

followed by

result.as("minutes");
Mark Dickson Jr.
  • 588
  • 4
  • 10
-2

If moment.js is too heavy for your use-case: I've wrapped up a small package to facilitate this:

import { parse, serialize } from 'tinyduration';
 
// Basic parsing
const durationObj = parse('P1Y2M3DT4H5M6S');
assert(durationObj, {
    years: 1,
    months: 2,
    days: 3,
    hours: 4,
    minutes: 5,
    seconds: 6
});
 
// Serialization
assert(serialize(durationObj), 'P1Y2M3DT4H5M6S');
Install using npm install --save tinyduration or yarn add tinyduration

See: https://www.npmjs.com/package/tinyduration

Melle
  • 7,639
  • 1
  • 30
  • 31