The previous post explained how to parse ISO 8601 duration strings using the Timex library.

As of Elixir 1.17, there's now a built-in way to handle this: Duration.from_iso8601/1.

It works as you’d expect:

Duration.from_iso8601("P1Y2M3DT4H5M6S")
# {:ok, %Duration{year: 1, month: 2, day: 3, hour: 4, minute: 5, second: 6}}

Duration.from_iso8601("P3Y-2MT3H")
# {:ok, %Duration{year: 3, month: -2, hour: 3}}

Duration.from_iso8601("-PT10H-30M")
# {:ok, %Duration{hour: -10, minute: 30}}

Duration.from_iso8601("PT4.650S")
# {:ok, %Duration{second: 4, microsecond: {650_000, 3}}}

To convert a Duration struct back into an ISO 8601 string, use Duration.to_iso8601/1:

Duration.to_iso8601(Duration.new!(year: 3))
# "P3Y"

Duration.to_iso8601(Duration.new!(day: 40, hour: 12, minute: 42, second: 12))
# "P40DT12H42M12S"

Duration.to_iso8601(Duration.new!(second: 30))
# "PT30S"

Duration.to_iso8601(Duration.new!([]))
# "PT0S"

Duration.to_iso8601(Duration.new!(second: 1, microsecond: {2_200, 3}))
# "PT1.002S"

Duration.to_iso8601(Duration.new!(second: 1, microsecond: {-1_200_000, 4}))
# "PT-0.2000S"

Other languages often have similar built-in support. For example, in PHP, you can use the DateInterval class:

$interval = new DateInterval('P34Y10M17D');
// DateInterval {#8359
//     interval: +34y 10m 17d
// }

$interval->format('P%dD');
// "P17D"

In some ecosystems, you may still need a third-party library to handle ISO 8601 durations. But in Elixir β‰₯ 1.17, it’s built in.