Home > Mobile >  Convert ISO8601 duration to seconds in typescript using date-fns
Convert ISO8601 duration to seconds in typescript using date-fns

Time:09-24

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.

  • Related