I have a ISO8601 duration string. ex. "PT1M14S" I want to convert this to seconds (Int) using date-fns package in typescript
CodePudding user response:
One solution is provided by package: iso8601-duration So we could do something like
import { parse, toSeconds } from 'iso8601-duration';
toSeconds(parse("PT1M14S"))
Please let me know date-fns provides any solution for this
CodePudding user response:
Parsing an ISO duration is half the problem, applying the values to a Date is the other half. The following is a simple parser that returns an object in the form {part: value}
like:
{year: 1, month, 3, hour: 1, minute: 2}
It only returns properties for tokens that are in the string. Some decent validation of the string needs to be added.
function parseISODuration(s) {
// QnD validation of string, need something smarter
// Should check tokens, order and values
// e.g. decimals only in smallest unit, W excludes other date parts
if (!/^P/.test(s)) return;
// Split into parts
let parts = s.match(/\d (\.\d )?[a-z]|T/gi);
// Flag for date and time parts, used to disambiguate month and minute
let inDate = true;
// Map of part tokens to words
let partMap = {Y:'year',M:'month',W:'week',D:'day',h:'hour',m:'minute',s:'second'}
return parts.reduce((acc, part) => {
// Set flag if reached a time part
if (part == 'T') {
inDate = false;
return acc;
}
// Disambiguate time parts (month/minute)
if (!inDate) {
part = part.toLowerCase();
}
// Add part name and value as a number
acc[partMap[part.slice(-1)]] = part.slice(0,-1);
return acc;
}, {});
}
// Examples
['P1Y2M1.5D', 'P1Y3M26DT3M', 'PT3H2M4.5S', 'P6W'].forEach(duration =>
console.log(`${duration} => ${JSON.stringify(parseISODuration(duration))}`)
);
Converting a duration to milliseconds is not trivial and must be done in the context of a start date. One approach is to copy the start date, add the appropriate values (a library can certainly help with that), then get the difference between the start and end dates.
That way issues like different month lengths and different day lengths (where daylight saving is observed) are taken into consideration by the Date instance and library, but there are plenty of questions with good answers here about adding years, months, days, etc. to a date so it's not hard to write your own functions to do that.