I've written in the past about the many quirks of Javascript dates. The good news is that there are plans for an entirely new piece of Javascript functionality to clean up what Date() does wrong. That functionality is called Temporal. In this guide we'll be covering why Temporal is better than Date(), and how to use it.
Support for Temporal
Temporal is currently stage 3 proposal which means that although a large portion of its functionality is stable, there may be some changes in the future. As the specification is not stable yet, no browser or backend Javascript has implemented the temporal specification. If you want to try out Temporal today, you can try this polyfill (use with caution in production).
What is Temporal?
Temporal consists of a bunch of big changes that are coming to Javascript to solve all the gripes developers have with Date()
. Temporal sets out a vision to solve most of the issues that exist, including:
- Strongly typed objects or dates, times, date/times, year/months, month/years, zoned date/times, and durations.
- Immutable objects (compared to the mutability of current Date() objects).
- Interoperability between standardized date formats.
- Support for all time zones and daylight saving's time safe arithmetic.
- Compliance with major date/time standards like ISO8601, RFC3339, and RFC5545.
- Full support for non-Gregorian calendars.
If you've been struggling with any issues that are inherent with Date
, some of these changes are pretty exciting.
New Types of Data in Temporal
One of the most exciting parts of Temporal is that we finally have different types for different measurements of time. In Date()
, all dates are timestamps underneath. With temporal, we are finally given a range of different types of date/time data. These are:
-
PlainDateTime
- the date and time combined. -
PlainDate
- the year, month, and day. -
PlainTime
- the time. -
PlainMonthDay
- the month and day. -
PlainYearMonth
- the year and month. -
Now
- similar to the current newDate()
implementation, returns the current instant. -
TimeZone
- the timezone. -
Calendar
- any calendar extensions -
ZonedDateTime
- the entire date and time, with timezone extensions and calendar extensions. -
Instant
- PlainDateTime plus timezone offset. -
Duration
- define a duration of time and may use years, months, weeks, days, hours, etc.
That means we can finally define a date, and have it mean a specific date, rather than a timestamp or date/time. Here is a breakdown of how each time or date type conforms with a standard date/time string:
Temporal Methods
The cool thing about how the Temporal functionality has been built is that every single type defined above has an associated constructor, and then methods for each of those objects. That means we have constructors like Temporal.PlainDate
, Temporal.Now
, Temporal.PlainTime
, Temporal.ZonedDateTime
, etc. Each of these have two common methods - .from()
, which lets us make a date or time from a set of data, and .compare()
, which lets us compare two dates or times.
Let's look at a few examples.
Defining a Date in Temporal
Let's say we want to create a date. Previously, we would've had to use new Date()
in Javascript, and even then this would've been a date/time
. With Temporal, we can use the PlainDate object, which only returns dates. Every constructor has two common methods: from, and compare, which let us create dates and times from a set of data, and to compare two sets of date/times.
If we want to create a PlainDate, we can do so by writing the following:
let myDate = Temporal.PlainDate.from({
year: 2022,
month: 03,
day: 28,
hour: 8,
second: 0,
minute: 44
});
Since this returns data of type PlainDate
, it will only return 2022-03-28, meaning no more worries about timezones, or the Unix epoch.
Further to that, we can gather data from that new PlainDate data point:
let myDate = Temporal.PlainDate.from({
year: 2022,
month: 03,
day: 28,
hour: 8,
second: 0,
minute: 44
});
myDate.year; // 2022
myDate.month; // 03
myDate.day; // 28
myDate.inLeapYear; // false
myDate.toString(); // 2022-03-28
Getting the current Unix Epoch
There will still be plenty of times when we need to get the current timestamp, but Temporal separates this functionality out from other valid functionality, such as date only, or timezone only constructors. Here are some examples:
let currentTime = Temporal.Now.instant(); // Current unix timestamp
Getting a time with Temporal
There are also some times when we only want to get the time, and not pollute that information with the date. We can use the PlainTime type to get that data. Another cool thing about Temporal is it goes down to nanoseconds, whereas currently in Javascript, we only have milliseconds.
The below code will return 08:44:00.068123434. As in our previous example, we can use from to create our PlainTime, and then get data off the back of that function using various methods:
let myDate = Temporal.PlainTime.from({
hour: 8,
second: 0,
minute: 44,
millisecond: 45,
microsecond: 123,
nanosecond: 434
});
myDate.hour; // 8
myDate.second; // 0
myDate.minute; // 44
myDate.millisecond; // 45
myDate.microsecond; // 123
myDate.nanosecond; // 434
myDate.toString(); // 08:44:00.068123434
Comparing two dates with Temporal
Comparing dates could be really difficult with Date()
, since we were often working from Unix epoch timestamps. With temporal, since we have date types, we can easily compare two dates using the compare()
method. It should be noted that all Temporal objects contain a method called compare()
, so comparing many different dates and times is really easy too. Here is an example comparing two dates:
let now = Temporal.Now.instant();
let checkDate = Temporal.PlainDate.from({
year: 2022,
month: 03,
day: 28
});
// Returns true when it is 2022-03-28
Temporal.PlainDate.compare(now, checkDate);
Creating a Regular Zoned Date Time
It's what we're sort of used to when working with Date()
, and we can easily create a full date/time with timezone in Temporal too. The same principles apply - we can use .from()
to create it, and we have access to a number of attributes too. We can also compare it against other dates and times using .compare()
:
let myDate = Temporal.PlainDate.from({
timeZone: 'Europe/Belfast',
year: 2022,
month: 03,
day: 28,
hour: 8,
second: 0,
minute: 44,
millisecond: 45,
microsecond: 123,
nanosecond: 434
});
myDate.year; // 2022
myDate.month; // 03
myDate.day; // 28
myDate.hour; // 8
myDate.second; // 0
myDate.minute; // 44
myDate.millisecond; // 45
myDate.microsecond; // 123
myDate.nanosecond; // 434
myDate.toString(); // 2022-03-28T08:44:00.068123434-00:00[Europe/Belfast]
Conclusion
Temporal is full of a lot more content. From the examples above, it's easy to see the value proposition that Temporal brings to Javascript, and why it's so exciting for date/time related features. I hope you've enjoyed this guide - here are some useful links if you want to keep reading: