“I must compare durations but they’re in ISO format (PT1H2M3S) – how do I convert them in a comparable duration unit with Power Automate?”
There’re two ways how you can get a duration. The more common one is to take two dates/times and calculate the difference, but some applications (e.g. Teams) give you the duration directly. A single ISO string with a specific format that contains all the information. For example, PT1H2M3S means 1 hour, 2 minutes, 3 seconds.
While it contains the whole duration, it’s not the best format to work with. It’s hard to read and impossible to compare. If you need to compare two such durations, you must convert them into a single unit, e.g. minutes or seconds. And that’s what this post is about.
Extract the numbers
The duration can be decomposed into multiple pieces. You’ve got the PT – information that it’s time, followed by the amount and units. And that’s what you must extract from there, the amount of units while converting it to the same unit, e.g. seconds.
The best expression for this job is the slice(…) expression. This expression has 3 parameters: string, start index and end index, and it’ll return a substring bounded by the two indexes.
slice(<string>, <startIndex>, <endIndex>)
e.g.
slice('string', 2, 6) = ring
Using the same expression on the ISO duration:
slice('PT1H2M3S', 2, 3) = 1 (hour)
But if you use it in a flow, you can’t use fixed numbers as the indexes. The number of units can have various number of digits, and you always need all of them. It can be one number or two numbers, and you always want only the number.
Get the indexes dynamically
That’s why you need another expression, the indexOf(…). This expression will find a string or a character in another string and return its position (starting from 0).
indexOf('string', 'r') = 2
By combining this expression with the slice(…) you can always find the position of the letters representing the unit, and extract the number in between. But if you used only the indexOf(…) it’d return the starting position of the string, hence including the whole string you searched for. You want to skip that one – if the string is ‘PT’, skip 2 characters by incrementing the returned index with the add(…) expression.
slice('PT1H2M3S',add(indexOf('PT1H2M3S','PT'),2),indexOf('PT1H2M3S','H'))
This expression will return just the number of hours. Convert it to an integer, multiply by 3600 seconds per hour, and you’ll get the hour part converted to seconds.
mul(int(slice('PT1H2M3S',add(indexOf('PT1H2M3S','PT'),2),indexOf('PT1H2M3S','H'))),3600)
The next step is to convert the minutes into seconds. Since minutes are between the H and M, the indexOf(…) expressions must search for these two letters.
mul(int(slice('PT1H2M3S',add(indexOf('PT1H2M3S','H'),1),indexOf('PT1H2M3S','M'))),60)
And the last part are the seconds between M and S. These are already in the correct unit so you don’t have to multiply them by anything.
int(slice('PT1H2M3S',add(indexOf('PT1H2M3S','M'),1),indexOf('PT1H2M3S','S')))
Add the numbers
Now, when you’ve got everything converted into the same unit, in this case seconds, you can add it all together.
add(
add(
mul(int(slice('PT1H2M3S',add(indexOf('PT1H2M3S','PT'),2),indexOf('PT1H2M3S','H'))),3600),
mul(int(slice('PT1H2M3S',add(indexOf('PT1H2M3S','H'),1),indexOf('PT1H2M3S','M'))),60))
,
int(slice('PT1H2M3S',add(indexOf('PT1H2M3S','M'),1),indexOf('PT1H2M3S','S')))
)
Although, this expression won’t work in all situations. The ISO duration always contains only the units that are needed. If the duration is less than 1 hour, it’ll start with minutes. If it’s less than 1 minute, it’ll start with seconds. That’s why you’ll need a condition in your flow where you check for the highest unit.
If the duration contains H, use the expression above. If it doesn’t, check if it contains M – in such situation the minutes will be between the PT and M and there’ll be no hours.
add(
mul(int(slice('PT2M3S',add(indexOf('PT2M3S','PT'),2),indexOf('PT2M3S','M'))),60),
int(slice('PT2M3S',add(indexOf('PT2M3S','M'),1),indexOf('PT2M3S','S')))
)
And if it doesn’t contain H nor M, it’ll contain only seconds between PT and S.
int(slice('PT3S',add(indexOf('PT3S','PT'),2),indexOf('PT3S','S')))
Summary
If you get the duration in the ISO format, you can use Power Automate to convert it into a single time unit. All you have to do is extract the specific number of units, multiply it to get the number in new units, and add it all together. Just be careful to handle all the possible durations lengths: >= 1 hour, => 1 minute, seconds only, eventually even the higher units like days, weeks, etc.