Temporal API Duration

Temporal API Duration

Working with Time Periods

🕚 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 API Cheatsheet: Site: screenshot show close-up on polyfill section of the site and includes details of how to install and import the polyfill for the Temporal A P I

💫 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:

Temporal API Duration: Track Listing: screenshot shows a table of nine track with length displayed for each one and also a total length."
    caption: "Temporal API Duration: Track Listing

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.

Did you find this article valuable?

Support Ask Rodney by becoming a sponsor. Any amount is appreciated!