Temporal API

the API to solve all the Date problems in JavaScript

Stefano Saffran
ProFUSION Engineering
6 min readMar 13, 2023

--

Hello guys,

In this post, we will be diving into the new JavaScript Temporal API and exploring its features and capabilities in detail.

Date and time are a crucial part of any application, whether it’s a simple to-do list or a complex scheduling system. Unfortunately, working with dates in JavaScript has been a challenge for many developers, due to the limited built-in functionality and inconsistencies across different browsers and environments. This has led to the popularity of libraries like Moment.js and DateFns, which provide a rich set of tools for working with dates. However, even with those libraries, there are still challenges with accuracy, consistency, and performance. Especially when we talk about time and timezones.

Dealing with times and timezones computationally can be challenging due to the complex nature of time. Time is not a constant and is affected by factors such as the Earth’s rotation, leap years, daylight saving time, and more. Additionally, timezones add another layer of complexity, as they are based on geopolitical boundaries rather than physical ones. It can also be particularly difficult when working with historical dates, as the timezone rules may have changed over time.

To solve this, here comes the Temporal API: The New Standard for Working with Dates in JavaScript.

The Temporal API is a new, standards-based approach in JavaScript to work with dates, times, durations, and periods. It is a global Object that acts as a top-level namespace (like Math) and provides a simple, consistent, and efficient way to perform a wide range of operations with temporal data, from parsing dates from strings to performing complex arithmetic calculations. The Temporal API is part of the ECMAScript Internationalization API and is based on the latest standards from the International Organization for Standardization (ISO). This means that it provides a reliable, high-quality solution that is backed by an international community of experts.

If you want to see more details about some of the problems JavaScript Date has and the motivations for Temporal, see Fixing JavaScript Date.

Why is the Temporal API better than current libraries?

There are several reasons why the Temporal API is a better solution than current libraries like Moment.js and DateFns.

  • As I said before, it is a standards-based API, which means that it provides a consistent and reliable way to work with dates and times that is not dependent on a single library and the way the creator drives it;
  • It is highly optimized for performance, with a focus on providing fast and efficient algorithms for working with temporal data;
  • It provides a rich set of features specifically designed for working with dates and times, such as built-in support for time zones, leap years, and leap seconds;
  • It is designed to be easy to use, with a simple and intuitive API that is easy to understand and integrate into your applications.

Now, let's take a look at some features of Temporal API

In this post, we’ll cover some of the most important data types and static methods available in Temporal. If you want to explore all of them, head over to the Temporal docs.

PlainDateTime

PlainDateTime represents a calendar date and wall-clock time that does not carry time zone information

To create a PlainDateTime object, you can use the Temporal.PlainDateTime constructor, which takes in a year, month, and day as required arguments, and also, hour, minute, second, millisecond, microsecond, nanosecond, and calendar as optional arguments, in that order.

const dateTime = new Temporal.PlainDateTime(2023, 2, 23, 10, 30, 0, 0);

This creates a PlainDateTime object representing February 23, 2023 at 10:30.

The temporal object offers many utility methods inside it.

const dateTime = new Temporal.PlainDateTime(2023, 2, 23, 10, 30, 0, 0);

console.log(dateTime.year);
// 2023
console.log(dateTime.hour);
// 10
console.log(dateTime.minute);
// 30
console.log(dateTime.nanosecond);
// 0
console.log(dateTime.calendar.toString());
// iso8601

An alternative way is to use the Temporal.Now object, that has several methods which give information about the current time and date.

Using Now we also have access to the same static methods we had using the PlainDateTime constructor.

const today = Temporal.Now.plainDateTimeISO()
console.log(today.toString());
// 2023-02-23T10:45:40.438072454
console.log(today.toPlainMonthDay().toString());
// '02-23'

ZonedDateTime

ZonedDateTime is a Temporal object that represents a date and time in the context of a specific time zone.

We can do the same as withPlainDateTime, using the Temporal.ZonedDateTimeconstructor, which takes in a required epochNanoseconds (bigint), and optional timeZone and calendar as arguments or we can also use Temporal.Now .

const zonedDateTime = new Temporal.ZonedDateTime(
1677265360653057483n, 'America/Campo_Grande', 'iso8601'
);
console.log(zonedDateTime.toString());
// 2023-02-24T15:02:40.653057483-04:00[America/Campo_Grande]
console.log(zonedDateTime.startOfDay().toString())
// 2023-02-24T00:00:00-04:00[America/Campo_Grande]
console.log(zonedDateTime.dayOfWeek);
// 5
console.log(zonedDateTime.day);
// 24
console.log(zonedDateTime.epochNanoseconds);
// 1677265360653057483n

const todayZoned = Temporal.Now.zonedDateTimeISO()
console.log(todayZoned.toString());
// 2023-02-23T16:44:32.454458232-04:00[America/Campo_Grande]

PlainDate

PlainDate object represents a calendar date that is not associated with a particular time or time zone.

const today = Temporal.Now.plainDateISO()
console.log(today.toString())
// 2023-02-23
const date1 = new Temporal.PlainDate(2023, 02, 19)
console.log(date1.toString())
// 2023-02-19
const date2 = Temporal.PlainDate.from("2023-02-19")
console.log(date2.toString())
// 2023-02-19
const date3 = Temporal.PlainDate.from({ year: 2023, month: 2, day: 19 })
console.log(date3.toString())
// 2023-02-19

Note that we used the static method from above, and there are quite a few of them and we’ll talk a little bit about them later.

PlainTime

PlainTime object represents a wall-clock time that is not associated with a particular date or time zone

const today = Temporal.Now.plainTimeISO()
console.log(today.toString())
// 16:36:50.739773623
const time1 = new Temporal.PlainTime(12, 25)
console.log(time1.toString())
// 12:25:00
const time2 = Temporal.PlainTime.from("05:43:17")
console.log(time2.toString())
// 05:43:17
const time3 = Temporal.PlainTime.from({ hour: 1, minute: 3, second: 44 })
console.log(time3.toString())
// 01:03:44

Instant

Instant is a single point in time (called "exact time"), with a precision in nanoseconds. It is always in UTC time , and no time zone or calendar information is present. To obtain local date/time units like year, month, day, or hour, a Temporal.Instant must be combined with a Temporal.TimeZone instance or a time zone string.

const now = Temporal.Now.instant()
console.log(now.toString())
// 2023-02-23T13:53:45.308214163Z

const dateInstant = Temporal.Instant.from("2000-01-01T00:00+04:00")
console.log(dateInstant.toString())
// 1999-12-31T20:00:00Z
console.log(dateInstant.year);
// => undefined

const tokyoZonedDateTime = dateInstant.toZonedDateTimeISO('Asia/Tokyo');
console.log(tokyoZonedDateTime.toString())
// 2000-01-01T05:00:00+09:00[Asia/Tokyo]'
console.log(tokyoZonedDateTime.year);
// 2000

Duration

Duration represents a duration of time that can be used in date/time arithmetic, and when printed, it produces a string according to the ISO 8601 notation for durations.

const duration = Temporal.Duration.from({ years: 1, days: 5, months: 22 });
console.log(duration.toString());
// P1Y22M5D
console.log(new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 888, 999, 0).toString());
// P1Y2M3W4DT5H6M7.888999S

const duration1 = Temporal.Duration.from({ hours: 2, minutes: 30, seconds: 10 });
// PT2H30M10S (2 hours, 30 minutes, and 10 seconds)
const duration2 = Temporal.Duration.from({ hours: 1, minutes: 45, seconds: 30 });
// PT1H45M30S (1 hours, 45 minutes, and 30 seconds)

// Adding two durations
const sum = duration1.add(duration2);
console.log(sum.toString());
// PT4H15M40S (4 hours, 15 minutes, and 40 seconds)

// Subtracting two durations
const difference = duration1.subtract(duration2);
console.log(difference.toString());
// PT44M40S (44 minutes and 40 seconds)

Static methods

There are several static methods in the API, we saw some of them in this post, like from , add and subtract . They provide utility functions for working with temporal data and you can use them to convert types, do some calculations, compare and sort dates, and much more.

Here are some examples of what we can do:

  • Calculate how many days are left until the end of the year
const today = Temporal.Now.plainDateTimeISO(); // get current date and time
const end = Temporal.PlainDate.from('2023-12-31'); // set the end of the year

const diff = Temporal.Duration.from({ days: today.until(end).days });
console.log(`Days until end of year: ${diff.days}`);
// Days until end of year: 310
  • Scheduling tasks
let start = Temporal.Now.plainDateTimeISO();
const duration = Temporal.Duration.from({ hours: 1, minutes: 30, seconds: 0 });
const end = start.add(duration);
const interval = Temporal.Duration.from({ minutes: 15 });

while (Temporal.PlainDateTime.compare(start, end) < 0) {
console.log(`Scheduled task for: ${start.toString()}`);
start = start.add(interval);
}
/*
Scheduled task for: 2023-02-23T15:51:50.394704559
Scheduled task for: 2023-02-23T16:06:50.394704559
Scheduled task for: 2023-02-23T16:21:50.394704559
Scheduled task for: 2023-02-23T16:36:50.394704559
Scheduled task for: 2023-02-23T16:51:50.394704559
Scheduled task for: 2023-02-23T17:06:50.394704559
*/
  • Flight arrival time in destination time zone (from docs)
const departure = Temporal.ZonedDateTime.from('2020-03-08T11:55:00+08:00[Asia/Hong_Kong]');
const flightTime = Temporal.Duration.from({ minutes: 775 });

const arrival = departure.add(flightTime).withTimeZone('America/Los_Angeles');
console.log(arrival.toString())
// '2020-03-08T09:50:00-07:00[America/Los_Angeles]'

As you can see the API provides a robust set of methods that can be really helpful in many different situations and will for sure simplify the developer's lives when it comes to working with dates and times in JavaScript.

How to use it?

The API is still a proposal in Stage 3 (meaning the draft is almost final and ready for last feedback) as of now (March 2023) and no browser supports it at the moment, but they should support it soon.

If you want to test it now, you can use this polyfill: @js-temporal/polyfill. Just install it and you’re ready to go.

References

That’s all! I hope you enjoyed reading it, bye!

--

--

Stefano Saffran
ProFUSION Engineering

Computer Engineer | Frontend Developer | Software Engineer at ProFUSION