Node/Js-module for parsing and making sense of ISO 8601 durations
A new standard is on it's way, see Temporal.Duration
Tests (most) in this module now validate against @js-temporal/polyfill
TL;DR
PnYnMnWnDTnHnMnS
-P<date>T<time>
.
(P) Years, Months, Weeks, Days (T) Hours, Minutes, Seconds.
Example:P1Y1M1DT1H1M1.1S
= One year, one month, one day, one hour, one minute, one second, and 100 milliseconds
Durations in ISO 8601 comes in 2 variants:
ISO 8601-1
Weeks are not allowed to appear together with any other units and durations can only be positive (used until v2.0.0 in this module).
Valid patterns with weeks: P2W
.
Invalid patterns with weeks: P2W2D
.
ISO 8601-2
An extension to the standard, allows combining weeks with other units (supported since v2.1.0 in this module).
Valid patterns with weeks: P2W
& P2W2DT5H
, etc.
ISO 8601-2 also allows for a sign character at the start of the string (-P1D
, +P1M
), this is not yet supported by this module.
- The
n
is replaced by the value for each of the date and time elements that follow then
. - Leading zeros are not required.
- Fractions are allowed on the smallest unit in the string, e.g.
P0.5D
orPT1.0001S
but notPT0.5M0.1S
.
Check out the details on Wikipedia or in the coming Temporal.Duration spec.
npm install iso8601-duration
Also available on jsr.io/@tolu/iso-8601-duration
Most noteworthy of the interface is the ability to provide a date
for toSeconds
-calculations.
Why becomes evident when working with durations that span dates as all months are not equally long.
E.g January of 2016 is 744 hours compared to the 696 hours of February 2016.
If a date is not provided for toSeconds
the timestamp Date.now()
is used as baseline.
export const toSeconds; // fn = (obj, date?) => number
export const pattern; // ISO 8601 RegExp
export const parse; // fn = string => obj
export default {
toSeconds,
pattern,
parse
}
Simple usage
import { parse, end, toSeconds, pattern } from "iso8601-duration";
console.log(parse("P1Y2M4DT20H44M12.67S"));
/* outputs =>
{
years: 1,
months: 2,
days: 4,
hours: 20,
minutes: 44,
seconds: 12.67
}
*/
console.log(toSeconds(parse("PT1H30M10.5S")));
// outputs => 5410.5
console.log(end(parse("P1D")));
// outputs => DateObj 2017-10-04T10:14:50.190Z
A more complete usecase / example
import { parse, toSeconds, pattern } from "iso8601-duration";
// convert iso8601 duration-strings to total seconds from some api
const getWithSensibleDurations = (someApiEndpoint) => {
// return promise, like fetch does
return new Promise((resolve) => {
// fetch text
fetch(someApiEndpoint)
.then((res) => res.text())
.then((jsonString) => {
// create new pattern that matches on surrounding double-quotes
// so we can replace the string with an actual number
const replacePattern = new RegExp(`\\"${pattern.source}\\"`, "g");
jsonString = jsonString.replace(replacePattern, (m) => {
return toSeconds(parse(m));
});
// resolve original request with sensible durations in object
resolve(JSON.parse(jsonString));
});
});
};