Ask almost any developer what their greatest fear is and one deep-seated topic will rise above the rest… dates. To be fair, this will mostly stem from where those dates originate. Are they coming directly as-is from a database? Were they formatted at the web service level? Are they in UTC or local time? So many questions, so few answers. There have been a number of libraries over the years to help developers manage dates and date arithmetic. The Temporal API brings web developers strongly typed, immutable objects, not just for various types of date
objects, but time, and even durations.
Date Math
A very popular use case for date arithmetic is adding and subtracting dates. Take for example an advanced search function. You want to search for all users that signed up for your website in the past week. Let’s do a quick comparison of how you might do that with regular date functions, and then use the Temporal API.
// Vanilla Date Functions
const today = new Date();
const lastWeek = new Date(today.setDate(today.getDate() - 7));
// Temporal API
const today = Temporal.Now.plainDateISO();
const lastWeek = today.subtract({ weeks: 1 });
Yes, this is possible with regular Date
functions, but using the Temporal API is very intuitive. I want to subtract a week, I can subtract a week. Add an hour, I can add an hour. This is the type of developer ergonomics one might have turned to third-party libraries for.
Taking a look at a practical example, we might have a list of employees with start dates that looks like this.
[
{
id: 1,
first_name: "Dorene",
last_name: "Lyokhin",
start_date: "2021-09-01"
},
{
id: 2,
first_name: "Veriee",
last_name: "Stichel",
start_date: "2021-08-23"
},
…
]
We might want to ask the question, “Who are the employees hired in the last six months?”. We can use the Temporal API compare method to compare two Temporal dates. Various types of Temporal dates have compare
methods, and since we are using PlainDate
in this example, we can use the PlainDate.compare.
const today = Temporal.Now.plainDateISO();
const target = today.subtract({ months: 6 });
const sixMonths = employees.filter((employee) => {
const current = Temporal.PlainDate.from(employee.start_date);
let result = Temporal.PlainDate.compare(current, target);
return result > 0;
});
Now we can easily use the Temporal API to find a date from 6 months ago and find any employees hired after that date. This is a great, simplified example of using the Temporal API to find a date in the past and compare it to the current date.
The Temporal API methods for arithmetic use Duration objects. The Duration objects provide any number of duration properties, from years, months, and days, to hours, minutes, seconds, milliseconds, microseconds, and nanoseconds. You can even derive Duration objects with the Temporal API.
// date is a Date object
// We want the duration since that time
let instant = Temporal.Instant.fromEpochMilliseconds(
date.getTime()
);
let duration = instant.since(Temporal.Now.instant());
The since method, like the compare method, is available for various Date objects with the Temporal API.
Maybe you need to figure out how many days until a certain event.
const now = Temporal.Now.plainDateISO();
// date six months from now, for demonstration
const upcoming = now.add({ months: 6 });
const days = now.until(upcoming).days;
// approximately 183, depending on the months ahead
This is an incredibly useful way you can find out if a customer has a bill coming up in a few days and quickly display a note or alert for the user. This could define some state of the application so the user can’t make changes within a certain timeframe as well.
Time zones
There are a number of date formats you can work with using the Temporal API. From PlainDate objects to Instant objects with nanosecond precision, and more! There is even a Calendar object you can create, but that also requires some working knowledge of the Intl API. Maybe next time!
Let’s take a quick look at working with time zones. I know you flinched, time zones are one aspect of working with dates that can be a pain point. This is because you may be working with date strings from sources that you don’t know exactly how they were generated. Most times, browser localization will help you work with dates and times. But maybe we need to do some work manually. That’s ok. The Temporal API can help us out here!
let timezone1 = Temporal.TimeZone.from('America/Los_Angeles');
let timezone2 = Temporal.TimeZone.from('Asia/Qatar');
let zoned1 = instant.toZonedDateTimeISO(timezone1);
let zoned2 = instant.toZonedDateTimeISO(timezone2);
zoned1.toString(); // '1995-12-31T16:00:01-08:00[America/Los_Angeles]'
zoned2.toString(); // '1996-01-01T04:00:01+04:00[Asia/Qatar]'
As you can see, the Temporal API will allow you to directly manage the time zones in your application so we can provide a cleaner experience for users of our applications. You can have a dashboard of information that provides dates and allow the user to change the time zone display of those dates via a drop-down, or user configuration so they can customize their experience.
Summary
There is a lot more you can do with the Temporal API, in particular when it comes to working with locales, time zones, and calendars. We just happen to think working with date math is one of the most accessible for most developers. We highly recommend you review the proposal, which is currently at stage 3. That means it’s near-final, but there are still some aspects of the API that may change before it’s completely finalized, so we would use caution if you are considering deploying its use with Polyfills to production.