Transforming Duration String to usuable numbers

Im building a clockify pack and they return any durations in a strange string format. Heres an example:

  • API Returns duration string as: PT45H15M
  • This should be transformed to: 45 hours and 15 minutes or 45.25 hours

On the Pack side, what is the best/easiest way to transform such a string to an actual duration unit? Some fancy Regex?

Thanks! (@Paul_Danyliuk , @Eric_Koleda , @Nick_HE any help here?)

1 Like

I won’t be of much help :sweat_smile: … But it’s an ISO duration (ISO 8601 - Wikipedia) :wink:

P stands for period :blush:T for time, etc…

In terms of conversions though, I stumbled upon this topic on StackOverflow: iso8601 - Convert ISO 8601 duration with JavaScript - Stack Overflow (:innocent:)

(Sorry @Scott_Collier-Weir I can’t help you here :innocent: )

This post explain it very well and gives a couple of options: How to parse ISO 8601 duration strings in JavaScript

The best option is to transform to seconds and use coda Duration value hint type to display it.

1 Like

And in case you haven’t seen it, here’s the docs on creating durations in Packs: Data types - Coda Pack SDK

1 Like

So, what I will need to do is transform my PT. . . string into one of these formats using regex?

My best guess would be to transform it into seconds and then let coda do the calculation on the backend to transform that into a duration type?

Dear goodness I have no idea how to do that
:raised_hands:
EDIT: Maybe I do

Heres what I went for:

let durationRaw = "PT1H30M15S";
let myRegex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/
let replaceAll = function (iso8601Duration) {
    var matches = iso8601Duration.match(myRegex);

    return {
        sign: matches[1] === undefined ? '+' : '-',
        years: matches[2] === undefined ? 0 : matches[2],
        months: matches[3] === undefined ? 0 : matches[3],
        weeks: matches[4] === undefined ? 0 : matches[4],
        days: matches[5] === undefined ? 0 : matches[5],
        hours: matches[6] === undefined ? 0 : matches[6],
        minutes: matches[7] === undefined ? 0 : matches[7],
        seconds: matches[8] === undefined ? 0 : matches[8]
    };
};
let myRanFunction = replaceAll(durationRaw)
let days = parseInt(myRanFunction.days, 10)
let hours = parseInt(myRanFunction.hours, 10)
let minutes = parseInt(myRanFunction.minutes, 10)
let seconds = parseInt(myRanFunction.seconds, 10)

let intoSeconds = (days*86400)+(hours*3600)+(minutes*60)+seconds;
console.log(`${intoSeconds} seconds`);

Can anyone help me out to let me know if this is fine? Or do you think I will run into issues? It was a mix of googling, then throwing together other random stuff and running the code over and over until it started working

Its kind of working I think:

2 Likes

My god that regex is terrifying, nice! :rofl:

I think I would just split on ‘T’ which gives you the time designation, then pull out each of the numbers into a variable.

const duration = "PT1H30M15S";
const timeComponent = duration.split("T")[1];
const hours = parseInt(timeComponent.split("H")[0]);
const minutes = parseInt(timeComponent.split("M")[0]);
const seconds = parseInt(timeComponent.split("S")[0]);

const totalSeconds = seconds + 60*minutes + 60*60*hours

I’m surprised that Javascript doesn’t have a built in parser for ISO 8601 Durations. Good SO answers here.

Generally, regex is good to avoid because it is really hard to read.

4 Likes

So glad you shared this post, Scott. I saw that Youtube just changed their durations to 8601 and I need to update. Also, thanks @Connor_McCormick1 for a simple solution!

3 Likes