Temporal API Duration: Working with Time Periods
Rodney Lab
Posted on August 8, 2022
🕚 Temporal API Duration
In this post on Temporal API duration, we see how the new JavaScript Temporal API makes working with time periods and durations easier. The API lets you define a time period as an object in hours, minutes and seconds etc., but also using ISO 8601 notation. ISO 8601 notation for duration crops up in a few places including Schema.org for web site SEO. There you might use it to describe the duration of a live performance, media object or even flight time. Not to worry if you do not know what the ISO 8601 notation is, we’ll take a look below. Even if you are not yet familiar with ISO 8601 notation, you may eventually find it a convenient way to initialise a time period. Here to help see how you can work with duration in the Temporal API we use the track list from Madonna’s 1980s chart topping album True Blue.
Temporal Polyfill
The Temporal API is still a TC39 proposal and as such is not yet an official JavaScript API and not recommended for production projects. That also means you need to use a polyfill to try it out. This is just a package which recognises the new API’s features and automatically translates them into code compatible with existing and established APIs.
There are a couple of APIs suggested on the TC39 site. I tried @js-temporal/polyfill
and have had no issues.
💫 Temporal.Duration.from()
The API provides a few ways to initialise a Temporal Duration. Probably, the most intuitive is:
const duration = Temporal.Duration.from({ days: 15, hours: 7});
Did you spot the Sinéad O’Connor reference in that example? If you have a period other than seven hours and 15 days, then you have access to years
, months
, weeks
, minutes
, seconds
and even milliseconds
, microseconds
and nanoseconds
, as well as days
and hours
.
🏅 ISO 8601 Notation
For many cases ISO 8601 is more convenient. This is just a string of letters and numbers in shorthand. An example is P15DT7H
. Here P
is just a marker that we are using an ISO 8601 period, T
(time) separates units shorter than a day from longer units. The 15D
is fifteen days and 7H
seven hours. The T
separator is needed since M
to the left of it represents months while, to the right, represents minutes. So you can appreciate if you want to note down a period of six years, five months, four days, three hours, two minutes and one second, you can succintly write P6Y5M4DT3H2M1S
. There is a W
(week) unit too, though this should not be used together with other units for maximum compatibility.
Back to the previous example, we can initiate the Temporal Duration using an ISO 8601 period thus:
const duration = Temporal.Duration.from("P15DT7H");
💿 Track List JSON Data
To see a few more Temporal duration methods, we will take a look a track list list from Madonna’s True Blue album. If you are not into 1980s music, fear not, this is the last 1980s artist reference in this post.
[
{
"title": "True Blue",
"artist": "Madonna",
"tracks": [
{ "number": 1, "title": "Papa Don’t Preach", "length": "PT4M39S" },
{ "number": 2, "title": "Open Your Heart", "length": "PT4M13S" },
{ "number": 3, "title": "White Heat", "length": "PT4M40S" },
{ "number": 4, "title": "Live to Tell", "length": "PT5M51S" },
{ "number": 5, "title": "Where’s the Party", "length": "PT4M21S" },
{ "number": 6, "title": "True Blue", "length": "PT4M18S" },
{ "number": 7, "title": "La Isla Bonita", "length": "PT4M2S" },
{ "number": 8, "title": "Jimmy Jimmy", "length": "PT3M55S" },
{ "number": 9, "title": "Love Makes the World Go Round", "length": "PT4M31S" }
]
}
]
We will build out a quick Astro app to help illustrate the other methods. However, don’t worry if you don’t know Astro; HTML and JavaScript appreciation is enough to follow along.
Here’s our output:
Notice how in the input JSON our track lengths use ISO 8601 durations. This is convenient as it creates short strings, which are easily serialisable as JSON too. We will initialise Temporal Durations using these ISO 8601 strings (like we saw earlier), then see how we can convert them to user friendly strings for our use case. Finally we will sum all the tracks lengths using the Temporal API to get a total playing time for the LP (album).
User Readable Durations
There is a .toLocaleString()
method on Temporal Durations which works in a similar way to the equivalent Temporal Date and Time methods. However, this relies on Intl.DurationFormat
support. That is another proposal which is not yet widely supported, so let’s roll our own and see some Temporal Duration manipulation methods in the process.
Temporal objects have minutes
and seconds
fields which contain those values as numbers (rather that strings). These let us write a simple function to convert the Temporal Duration objects to string for display:
function stringFromDuration(iso8601Duration: string): string {
const { minutes, seconds, } = Temporal.Duration.from(iso8601Duration);
return `${minutes}:${seconds.toString(10).padStart(2, "0")}`;
}
This takes an input like PT4M39S
and returns 4:39
. We pad the seconds so that, for example, four minutes and two seconds gets written 4:02
, as would be expected by a user or site visitor. We use this function to convert track lengths from ISO 8601 strings to the strings we see in the image.
Temporal Duration Arithmetic
We can easily add durations using the Temporal.Duration.add
method:
const totalDuration = durationA.add(durationB);
That creates a new Temporal.Duration object. For years, months and weeks, the intent could be ambiguous so you need also to provide an object with a relativeTo
date field as a second argument.
We use add
to work out the total track time using the array reduce method:
const totalLength = tracks.reduce(
(accumulator, { length }) => accumulator.add(Temporal.Duration.from(length)),
new Temporal.Duration(),
);
Here accumulator
keeps a running total of the duration as we loop through the members of the array. Each array member is an object with a length
field, the duration of the track as an ISO 8601 string. We initialise the accumulator with new Temporal.Duration()
, equivalent to zero duration.
You could do this manipulation manually by parsing the durations and converting them to seconds, summing and then converting the output to human readable string. That is no way to live your life though! More seriously, using the Temporal API Duration object should result in more robust, less error prone code which is also cleaner and easier to understand. There is a similar subtract
method as well as absolute, rounding and negation methods. See the TC39 docs for more details.
🙌🏽 Temporal API Duration: Wrapping Up
We have had an introduction to the Temporal API Duration. In particular, we saw:
- how to initialise a Temporal Duration from an object or ISO 8601 string,
- what an ISO 8601 duration string is ,
- also how you can sum durations using the Temporal API.
Open up the Astro project we referenced from the Rodney Lab GitHub repo to play around.
I hope you found this article useful and am keen to hear how you will use the starter on your own projects as well as possible improvements.
🙏🏽 Temporal API Duration: Feedback
Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, please consider supporting me through Buy me a Coffee.
Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter and also askRodney on Telegram. Also, see further ways to get in touch with Rodney Lab. I post regularly on Astro as well as SvelteKit. Also subscribe to the newsletter to keep up-to-date with our latest projects.
Posted on August 8, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.