How to parse ISO 8601 duration strings in JavaScript
Time to read: 4 minutes
If you've encountered a duration string that looks like P1DT12H36M
and been confused about what to do with it, then you're in the right place. Much like parsing phone numbers, while you can write a regular expression to parse a duration, I don't recommend it.
What is an ISO 8601 duration?
ISO 8601 is a set of standardized date and time formats in an attempt to tame every programmer's favorite challenge. Durations represent the amount of time between two dates or times.
This format displays a duration in the following format: PnYnMnDTnHnMnS
where n
is the number for the corresponding interval:
- Y = years
- M = months
- W = weeks
- D = days
- T = delineator between dates and times, necessary to disambiguate between months and minutes
- H = hours
- M = minutes
- S = seconds
You can leave certain intervals off if they don't apply, but you must include the T
before any time intervals (P<date>T<time>
). Valid examples include:
P3Y6M4DT12H30M5S
(3 years, 6 months, 4 days, 12 hours, 30 minutes, and 5 seconds)P3DT12H
(3 days and 12 hours)P1M
(1 month)PT1M
(1 minute)PT0S
(0)P0.5Y
(1/2 a year)PT1M3.025S
(1 minute and 3025 milliseconds)
You can use decimals in the last and smallest value like in the 0.5Y or 3.025S examples above. You can also ignore "carry over points" like 24 hours or 60 seconds so PT36H and PT1D12H are both valid. Like any date or time problem there can be gotchas, so "keep in mind that 'PT36H' is not the same as 'P1DT12H' when switching from or to Daylight saving time." [source]
Does JavaScript have native support for durations?
There is no API to parse durations in JavaScript's Date API. However, durations are part of the Temporal proposal. Learn more about Temporal on the Igalia blog.
I've included 3 ways to parse durations in JavaScript in this blog post, they all have their pros and cons:
- Temporal
- tinyduration
- moment.js
How to parse a duration with Temporal
This is not recommended for production use yet, but the interface is really great and I'm hopeful it will become the standard solution soon. Head over to https://tc39.es/proposal-temporal/docs/duration.html and open up the developer tools console (Chrome instructions) in your browser. The polyfill is automatically included in the DevTools for experimentation so you don't have to install anything.
Parse an ISO 8601 duration string with the following code:
From the Duration
object in the d
variable, you can access elements or calculate totals:
If the duration contains a year, month, or week, you'll need to include a "relative" date. Skipping the relativeTo parameter will result in the error Uncaught RangeError: a starting point is required for balancing calendar units
(learn more).
Fix the error by adding a relative date:
You can even add durations together:
Or round to the nearest unit of time:
Learn more about what's possible in the Temporal documentation.
How to parse a duration with tinyduration
I found tinyduration in a Stack Overflow post. From my testing it effectively does the job and seems maintained.
Install the library (you'll need Node.js and npm or Yarn):
- NPM:
npm install --save tinyduration
- Yarn:
yarn add tinyduration
Open the Node.js REPL from your terminal (type node
) and type in or paste the following code:
The parse
method returns a simple object containing the relevant duration details, and you can also serialize objects back to ISO 8601 string durations. Unfortunately, you'll have to do additional work or use another library to convert that to something aggregate like milliseconds, but depending on your needs this might be a good option.
How to parse a duration with moment.js
Unfortunately moment.js is a large library with known issues (including one specific to durations). However, this library provides a lot of useful tools that the native Date API does not. It is also more powerful than options like tinyduration
because it offers things like converting durations to milliseconds or friendlier strings so it's an option until Temporal is production ready.
Install the library (detailed installation instructions):
- NPM:
npm install --save moment
- Yarn:
yarn add moment
Open the Node.js REPL from your terminal (type node
) and type in or paste the following code:
Learn more about working with durations using in the Moment.js documentation.
Where are ISO 8601 durations used?
I first discovered this duration format in recipe metadata. According to the Schema.org Recipe standard, things like cook time should be represented as a duration. The schema will also infer total time from prep time and cook time if it's not explicitly provided.
Bonus soup recipe
Twilio also uses durations in our new SIM Swap package in the Lookup API. Since data varies by country and may not include a specific swapped date, we also include a swapped period that's represented by a duration. A sample response to a SIM Swap Lookup would look like this:
To check if the SIM swap occurred in the last day you could do something like this with moment.js:
To format durations in human-readable format you might like the Humanize Duration library. It can easily turn 110809805000
milliseconds into '3 years, 6 months, 4 days, 3 hours, 30 minutes, 5 seconds'
. Learn how to use the project in its documentation.
Have you encountered ISO 8601 durations in the wild? Let me know where. Find me on Twitter @kelleyrobinson.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.