First Look at the Temporal API in JavaScript
Working with dates in JavaScript sucks. In the 2021 State of JS survey, developers voted for Date management as one of the core pain points of JavaScript.
There are many libraries out there to fix the lacking functionality of the built-in Date API, but they are only patching a core functionality that should be easy to use out of the box, without any additional libraries. Luckily for us, there could be a solution.
The Temporal API, an experimental proposal that is currently in stage 3 aims to solve the problems that the current Date API has, and makes working with dates in JavaScript much simpler.
Why do we need a new API?
First things first, why do we need a new API in the first place? There are a couple of issues with the current Date API that the Temporal API fixes, and supports out of the box. These are:
- Easy to use API for working with date and time
- Support for all time zones
- Dealing with objects representing fixed dates and times
- Making objects immutable
- Support for non-Gregorian calendars
How to Get Started with the Temporal API
While the Temporal API is still in an experimental phase, you can try it out today using one of the methods below:
- Installing it as a polyfill with NPM
- Try out in your console on the official website
To install it as a polyfill with NPM and try it out in your codebase, run the following command in your terminal:
npm i @js-temporal/polyfill
To try it out inside your DevTools console, head over to the official page, and open up your console, then type in Temporal
. On this object, you will have access to all the features the Temporal API currently supports.
Instant: Ζ, Calendar: Ζ, PlainDate: Ζ, PlainDateTime: Ζ, Duration: Ζ, β¦}
Calendar: Ζ Calendar(id)
Duration: Ζ Duration()
Instant: Ζ Instant(epochNanoseconds)
Now: Temporal.Now {instant: Ζ, plainDateTime: Ζ, plainDateTimeISO: Ζ, plainDate: Ζ, plainDateISO: Ζ, β¦}
PlainDate: Ζ PlainDate(isoYear, isoMonth, isoDay)
PlainDateTime: Ζ PlainDateTime(isoYear, isoMonth, isoDay)
PlainMonthDay: Ζ PlainMonthDay(isoMonth, isoDay)
PlainTime: Ζ PlainTime()
PlainYearMonth: Ζ PlainYearMonth(isoYear, isoMonth)
TimeZone: Ζ TimeZone(timeZoneIdentifier)
ZonedDateTime: Ζ ZonedDateTime(epochNanoseconds, timeZone)
Core Functionality of the API
Let's try to get familiar with the API and see what are its core functionalities. A common example is getting the current date and time. This can be done in the following way:
// Using the Date object
new Date()
// Using the Temporal API
Temporal.Now.zonedDateTimeISO().toString()
Notice that we called toString
on the return value. This is because Temporal returns an object that contains all of the metadata associated with the date, including:
{
day: 13
dayOfWeek: 3
dayOfYear: 194
daysInMonth: 31
daysInWeek: 7
daysInYear: 365
epochMicroseconds: 1657709945222890n
epochMilliseconds: 1657709945222
epochNanoseconds: 1657709945222890429n
epochSeconds: 1657709945
era: undefined
eraYear: undefined
hour: 12
hoursInDay: 24
inLeapYear: false
microsecond: 890
millisecond: 222
minute: 59
month: 7
monthCode: "M07"
monthsInYear: 12
nanosecond: 429
offset: "+02:00"
offsetNanoseconds: 7200000000000
second: 5
timeZone: TimeZone
weekOfYear: 28
year: 2022
}
So you can actually call all of the above properties right on the date to get whatever information you need. For example, the day or the month. But in fact, Temporal.Now
has many more methods that you can call, including the following:
// Return date, eg '2022-07-13'
new Date().toISOString().split('T')[0]
Temporal.Now.plainDateISO().toString()
// Return time, eg '13:11:30.674687326'
new Date().toISOString().split('T')[1]
Temporal.Now.plainTimeISO().toString()
// Return date and time, eg '2022-07-13T13:12:14.426724658'
new Date().toISOString()
Temporal.Now.plainDateTimeISO().toString()
Again, these are all objects, from which you can also get properties, which is not something you can do with the Date API. For example, let's see how you would get the year, month, and day using one of the above methods:
// Using Date
const year = new Date().getFullYear()
const month = new Date().getMonth() + 1
const day = new Date().getDate()
// Using Temporal
const year = Temporal.Now.plainDateISO().year
const month = Temporal.Now.plainDateISO().month
const day = Temporal.Now.plainDateISO().day
You can also construct new dates and times from variables, using Temporal.PlainDate.from
and Temporal.PlainTime.from
respectively.
// Returns '2022-07-13'
Temporal.PlainDate.from({ year: 2022, month: 7, day: 13 }).toString()
// Returns '12:00:13'
Temporal.PlainTime.from({ hour: 12, minute: 0, second: 13 }).toString()
How to Change Dates with Temporal
But what really makes the Temporal API powerful, is its ability to easily manipulate dates. Let's see how you can get yesterday, and tomorrow using both the Date and Temporal API:
// Get yesterday and tomorrow using Date
// Returns Tue Jul 12 2022 13:37:59 GMT+0200 (Central European Summer Time)
const yesterday = new Date()
const tomorrow = new Date()
yesterday.setDate(yesterday.getDate() - 1)
tomorrow.setDate(tomorrow.getDate() - 1)
// Get yesterday using Temporal
// Returns '2022-07-12'
Temporal.Now.plainDateISO().subtract({ days: 1 }).toString()
Temporal.Now.plainDateISO().add({ days: 1 }).toString()
We can use subtract
and add
to remove or add days to the current date. We can also do this with constructed dates. And you can not only subtract or add days, you can also do this with months and years. The API is also capable of doing the same thing with time. This would be extremely cumbersome with the Date API.
// Adding months and years to a date
// Returns '2028-01-14'
Temporal.Now.plainDateISO().add({
days: 1,
months: 6,
years: 5
}).toString()
// Adding hours, minutes and seconds
// Returns '15:07:31.771807196'
Temporal.Now.plainTimeISO().add({
hours: 1,
minutes: 20,
secounds: 5
}).toString()
How to Compare Dates with Temporal
The Temporal API is also capable of comparing two different dates. For example, if you would like to compare whether two dates are the same, you can do the following:
const date1 = Temporal.Now.plainDateISO()
const date2 = Temporal.Now.plainDateISO()
// βοΈ This will return true
date1.equals(date2)
// β This will return false
date1 === date2
Notice that date1 === date2
will not work because their reference will be different.
You can also get the amount of time passed between two dates. Let's increase the month of date2
by one and do a comparison again. Surely enough, the two dates will not be the same, but we can also get the time passed between them.
const date1 = Temporal.Now.plainDateISO()
const date2 = Temporal.Now.plainDateISO().add({ months: 1 })
// This will return false
date1.equals(date2)
// This will return 'P31D'
date1.until(date2).toString()
// This will return '-P31D'
date1.until(date2).toString()
We can use either until
or since
to do comparisons between two dates. The return value means that there are 31 days between the two dates. Notice that until
returns a negative value, because date2
is in the future. If we change the variables around, the positive/negative values will also be switched.
This kind of comparison can also be done with days or years, and even with time. You can also construct new Date objects from existing Date objects using the with
method:
// Returns '2022-07-13'
const date1 = Temporal.Now.plainDateISO()
// This will now return '2022-01-13'
const date2 = date1.with({ month: 1 }).toString()
How to Sort Dates with Temporal
Dates can also be sorted with the Temporal API. Let's say you have 5 different dates in random order. We can use the compare
method on PlainDate
to sort them in ascending order.
const date1 = Temporal.Now.plainDateISO()
const date2 = Temporal.Now.plainDateISO().subtract({ years: 20 })
const date3 = Temporal.Now.plainDateISO().add({ years: 20 })
const date4 = Temporal.Now.plainDateISO().add({ years: 5 })
const date5 = Temporal.Now.plainDateISO().subtract({ years: 5 })
const dates = [date1, date2, date3, date4, date5].map(date => date.toString())
<- ['2022-07-13', '2002-07-13', '2042-07-13', '2027-07-13', '2017-07-13']
const sorted = dates.sort(Temporal.PlainDate.compare)
<- ['2002-07-13', '2017-07-13', '2022-07-13', '2027-07-13', '2042-07-13']
How to Work with Durations
Last but not least, you can also use the Temporal API to calculate durations. Let's say you want to convert hours and minutes into seconds. You can do this using Temporal.Duration
.
// This will return 7200
Temporal.Duration.from({ hours: 2 }).total({ unit: 'second' })
Here we are constructing a new Duration
object with two hours, and then we say we want to get the total time passed in seconds. You can of course pass minutes or hours too, depending on how you want to calculate a duration.
Summary
In summary, the new Temporal API looks very promising, and you can try it out right now and experiment with it using the above-mentioned methods. Since this is still the experimental phase, avoid using it in production, but do try it out and report any bugs you spot through GitHub. If you would like to read more about the API, head over to the official documentation.
What are your current pain points when working with the Date API? Let us know in the comments below! Thank you for reading through, happy experimenting! π¨βπ»
Rocket Launch Your Career
Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies: