# Is It Time for the JavaScript Temporal API?

#### Learn what’s coming with the implementation of this phase-3 ECMA proposal

Temporal API

Date handling in JavaScript is *ugly*. The `[Date()](https://developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Date)` [object](https://developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Date) has not changed since the first Java-inspired implementation in 1995. Java scrapped it but `Date()` remained in JavaScript for backward browser compatibility.

Issues with the `Date()` API include:

*   it’s inelegant
*   it only supports UTC and the user’s PC time
*   it doesn’t support calendars other than Gregorian
*   string to date parsing is error-prone
*   `Date` objects are mutable - for example:

const today = new Date();  
const tomorrow = new Date( today.setDate( today.getDate() + 1 ) );

console.log( tomorrow );  // is tomorrow's date  
console.log( today );     // is also tomorrow's date!

Developers often turn to date libraries such as [moment.js](https://momentjs.com/) but it’s a 74Kb payload and dates remain mutable. Modern alternatives such as [Day.js](https://day.js.org/) and [date-fns](https://date-fns.org/) may be better but should a library necessary when your app has minimal date-handling requirements?

Browsers must continue to support `Date()` but a new `Temporal` static global date object is at the [Stage 3 Candidate Proposal in the TC39 standards approval process](https://tc39.es/proposal-temporal/) (the final stage before implementation). The API addresses all the issues above and it's [coming to the Chrome browser soon](https://chromestatus.com/feature/5668291307634688). It's unlikely to have widespread implementation until late 2022 so be wary that changes could occur.

### Current Date and Time

`[Temporal.Now](https://tc39.es/proposal-temporal/docs/#Temporal-Now)` returns an object representing the current date and time. Further methods provide information such as:

// time since the Unix epoch on 1 Janary, 1970 UTC  
Temporal.Now.instant().epochSeconds;  
Temporal.Now.instant().epochMilliseconds;

// time in current location  
Temporal.Now.zonedDateTimeISO();

// current time zone  
Temporal.Now.timeZone();

// current time in another time zone  
Temporal.Now.zonedDateTimeISO('Europe/London');

### Instant Dates and Times

`[Temporal.Instant](https://tc39.es/proposal-temporal/docs/#Temporal-Instant)` returns an object representing a date and time to the nearest nanosecond according to an ISO 8601 formatted string:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1660399232306/Q0b4Yy9rd.png)

Temporal.Instant.from('2022-03-04T05:56:78.999999999+02:00\[Europe/Berlin\]');  
Temporal.Instant.from('2022-03-04T05:06+07:00');

You can also use an epoch value:

Temporal.Instant.fromEpochSeconds(1.0e8);

### Zoned Dates and Times

`[Temporal.ZonedDateTime](https://tc39.es/proposal-temporal/docs/#Temporal-ZonedDateTime)` returns an object representing a timezone and calendar-aware date/time at the instant an event occurred (or will occur) in a particular global location, e.g.

new Temporal.ZonedDateTime(  
  1234567890000, // epoch nanoseconds  
  Temporal.TimeZone.from('Europe/London'), // timezone  
  Temporal.Calendar.from('iso8601') // default calendar  
);

Temporal.ZonedDateTime.from('2025-09-05T02:55:00+02:00\[Africa/Cairo\]');

Temporal.Instant('2022-08-05T20:06:13+05:45').toZonedDateTime('+05:45');

Temporal.ZonedDateTime.from({  
  timeZone: 'America/New\_York'  
  year: 2025,  
  month: 2,  
  day: 28,  
  hour: 10,  
  minute: 15,  
  second: 0,  
  millisecond: 0,  
  microsecond: 0,  
  nanosecond: 0  
});

### Plain Dates and Times

*Plain* dates and times reference simpler calendar events which are not associated with a specific time zone. The options include:

*   `[Temporal.PlainTime](https://tc39.es/proposal-temporal/docs/#Temporal-PlainTime)` refers to a specific time, e.g. “the meeting occurs at 3pm every weekday”:

// both are 15:00:00  
new Temporal.PlainTime(15, 0, 0);  
Temporal.PlainTime.from(‘15:00:00’);

*   `[Temporal.PlainDate](https://tc39.es/proposal-temporal/docs/#Temporal-PlainDate)` refers to a specific date, e.g. “your tax return is due by January 31, 2022”:

// both are January 31, 2022  
new Temporal.PlainDate(2022, 1, 31);  
Temporal.PlainDate.from(‘2022–01–31’);

*   `[Temporal.PlainDateTime](https://tc39.es/proposal-temporal/docs/#Temporal-PlainDateTime)` refers to a date and time without a time zone:

// both are 4 May 2022 at 10:11am and 12 seconds  
new Temporal.PlainDateTime(2022, 5, 4, 10, 11, 12);  
Temporal.PlainDateTime.from(‘2022–05–04T10:11:12’);

*   `[Temporal.PlainYearMonth](https://tc39.es/proposal-temporal/docs/#Temporal-PlainYearMonth)` refers to a date without a day, e.g. “the June 2022 schedule is ready”:

// both are June 2022  
new Temporal.PlainYearMonth(2022, 6);  
Temporal.PlainYearMonth.from(‘2022–06’);

*   `[Temporal.PlainMonthDay](https://tc39.es/proposal-temporal/docs/#Temporal-PlainMonthDay)` refers to a date without a year, e.g. “Star Wars day is on May 4”:

// both are May 4  
new Temporal.PlainMonthDay(5, 4);  
Temporal.PlainMonthDay.from('05-04');

### **Date and Time Values**

You can extract specific date and time values from a `Temporal` object. Assuming the following date and time:

const t1 = Temporal.ZonedDateTime.from('2022-12-07T03:24:30+02:00\[Africa/Cairo\]');

you can extract:

t1.year;        // returns 2022  
t1.month;       // 12  
t1.day;         // 7  
t1.hour;        // 3  
t1.minute;      // 24  
t1.second;      // 30  
t1.millisecond; // 0  
t1.microsecond; // 0  
t1.nanosecond;  // 0

Other useful properties include:

*   `dayOfWeek` — returns `1` for Monday to `7` for Sunday
*   `dayOfYear` — returns `1` to `365` or `366` on leap years
*   `weekOfYear` — returns `1` to `52` or `53`
*   `daysInMonth` — returns `28`, `29`, `30`, or `31`
*   `daysInYear` — returns `365` or `366`
*   `inLeapYear` — returns `true` for a leap year or `false` when not

### Comparing and Sorting Dates and Times

All `Temporal` objects have a `.compare(date1, date2)` method which returns:

*   `0` when `date1` and `date2` are the same
*   `1` when `date1` occurs after `date2`, or
*   `-1` when `date1` occurs before `date2`

For example:

const  
  date1 = Temporal.Now,  
  date2 = Temporal.PlainDateTime.from('2022-05-04');

Temporal.ZonedDateTime.compare(date1, date2);  
// returns 1 when May 4, 2022 arrives

You can pass the `compare()` method as an Array `sort()` function to arrange dates into ascending chronological order (earliest to latest):

const t = \[

  '2022-01-01T00:00:00+00:00\[Europe/London\]',  
  '2022-01-01T00:00:00+00:00\[Africa/Cairo\]',  
  '2022-01-01T00:00:00+00:00\[America/New\_York\]'

\].map( d => Temporal.ZonedDateTime.from(d) )  
 .sort( Temporal.ZonedDateTime.compare );

### Date and Time Calculations

All `Temporal` objects offer math methods to [add()](https://tc39.es/proposal-temporal/docs/duration.html#add), [subtract()](https://tc39.es/proposal-temporal/docs/duration.html#subtract), or [round()](https://tc39.es/proposal-temporal/docs/duration.html#round) to a duration.

You can define a duration as a `[Temporal.Duration](https://tc39.es/proposal-temporal/docs/duration.htm)` [object](https://tc39.es/proposal-temporal/docs/duration.htm) which sets a period in `years`, `months`, `weeks`, `days`, `hours`, `minutes`, `seconds`, `milliseconds`, `microseconds`, and `nanoseconds` as well as a `sign` for `-1` negative or `1` positive durations. However, all these methods accept a duration-like value without the need to create a specific object. Examples:

const t1 = Temporal.ZonedDateTime.from('2022-05-04T00:00:00+00:00\[Europe/London\]');

// add 8 hours 59 minutes  
t1.add({ hours: 8, minutes: 59 }); // or  
t1.add(Temporal.Duration.from({ hours: 8, minutes: 59 }));

// subtract 2 weeks  
t1.subtract({ weeks: 2 }); // or  
t1.add({ weeks: 2, sign: -1 });

// round to nearest month  
t1.round({ smallestUnit: 'month' });

*Plain* dates and times can wrap so adding 24 hours to a `PlainTime` returns a new `Temporal` object with an identical value.

The `until()` and `since()` methods return a `Temporal.Duration` object describing the time until or since a specific date and time based on the current date/time, e.g.

// months to t1  
t1.until().months;

// days to t2  
t2.until().days;

// weeks since t3  
t3.since().weeks;

The `equals()` method also determines whether two date/time values are identical:

const  
  d1 = Temporal.PlainDate.from('2022-01-31');  
  d2 = Temporal.PlainDate.from('2023-01-31');

d1.equals(d2); // false

### Formatting Date and Time Strings

All `Temporal` objects have a string representation returned when using the `.toString()` method, e.g. `Temporal.Now.toString()`:

2022-09-05T02:55:00+02:00\[Europe/London\]

This is not user friendly but the [Internationalization API](https://blog.openreplay.com/the-complete-guide-to-localizing-your-app-with-javascript-s-internationalization-api) offers a better alternative with localisation options. For example:

// define a date  
const d = new Temporal.PlainDate(2022, 3, 14);

// US date format: 3/14/2022  
new Intl.DateTimeFormat('en-US').format(d);

// UK date format: 14/03/2022  
new Intl.DateTimeFormat('en-GB').format(d);

// Spanish long date format: miércoles, 14 de abril de 2022  
new Intl.DateTimeFormat('es-ES', { dateStyle: 'full' }).format(d);

This is not part of the `Temporal` API and there's no guarantee the `[Intl](https://developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Intl)` [(Internationalization) API](https://developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Intl) will support `Temporal` as well as `Date` objects - although there would be a developer outcry if it didn't!

### Open Source Session Replay

Debugging a web application in production may be challenging and time-consuming. [OpenReplay](https://github.com/openreplay/openreplay) is an Open-source alternative to FullStory, LogRocket and Hotjar. It allows you to monitor and replay everything your users do and shows how your app behaves for every issue. It’s like having your browser’s inspector open while looking over your user’s shoulder. OpenReplay is the only open-source alternative currently available.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1660399234383/KWF0xIMno.png)

Happy debugging, for modern frontend teams — [Start monitoring your web app for free](https://github.com/openreplay/openreplay).

### Temporal Time

We’ve accepted the dodgy `Date()` since day one but `Temporal` gives JavaScript developers something to look forward to. The days of resorting to a date library are nearly over.

For further information, refer to:

1.  [The](https://tc39.es/proposal-temporal/) `[Temporal](https://tc39.es/proposal-temporal/)` [proposal](https://tc39.es/proposal-temporal/)
2.  [The](https://tc39.es/proposal-temporal/docs/) `[Temporal](https://tc39.es/proposal-temporal/docs/)` [documentation](https://tc39.es/proposal-temporal/docs/)
3.  [The](https://tc39.es/proposal-temporal/docs/cookbook.html) `[Temporal](https://tc39.es/proposal-temporal/docs/cookbook.html)` [cookbook examples](https://tc39.es/proposal-temporal/docs/cookbook.html)

*Originally published at* [*https://blog.openreplay.com*](https://blog.openreplay.com/is-it-time-for-the-javascript-temporal-api) *on December 26, 2021.*
