- Temporal Time
- Current Date and Time
- Creating Instant Date/Times
- Creating Zone-aware Date/Times
- Creating Plain Dates and Times
- Extracting Values
- Comparing and Sorting Dates
- Date Calculations
- Formatting Dates With the Internationalization API
- About Time?
- Frequently Asked Questions (FAQs) about JavaScript Temporal API
Whatever your opinion of JavaScript, everyone thinks date handling is a mess. The Date()
object implementation was copied directly from Java in 1995. Java scrapped it two years later but it remained in JavaScript for backward compatibility.
These are the problems we face with Date()
:
- it only supports UTC and the user’s local time
- there’s no support for non-Gregorian calendars
- daylight-saving behavior is unpredictable
- parsing dates from strings is unreliable
- the API is clunky
Date
objects are mutable: a date will change as methods are applied
The most popular alternative used to be the Moment.js date library . However, this has been placed in maintenance mode and should not really be used in new projects. They recommend a couple of alternatives, but each of these have their own pros and cons.
The Date()
object can’t be removed from JavaScript, but a new Temporal
option is at stage 2 in the TC39 standards approval process. The properties and methods discussed here are subject to change, but the API should arrive in browsers and runtimes some time in 2021.
Temporal Time
Temporal
is a top-level static global object (like Math
).
Its main objectives are:
- a predictable cross-browser/runtime behavior
- easier APIs for date and time computations
- support for non-Gregorian calendars
- support for all time zones, including daylight-saving arithmetic
- parsing of strictly specified ISO-8601 strings
- making all objects immutable
The API is comprehensive and may change, but you can look forward to the following key features at some point in the near future.
Current Date and Time
Temporal.now
returns the current date/time, which can be passed to further methods to provide additional information. For example:
// exact time since the Unix epoch on 1 Janary, 1970 UTC
Temporal.now.instant();
Temporal.now.instant().epochSeconds;
Temporal.now.instant().epochMilliseconds;
// current time zone
Temporal.now.timeZone();
// time in current location, e.g.
// 2021-09-18T04:17:48.435068431-04:00[America/New_York]
Temporal.now.zonedDateTimeISO();
// time in another time zone, e.g.
// 2021-09-18T09:17:48.438068435+01:00[Europe/London]
Temporal.now.zonedDateTimeISO('Europe/London');
Creating Instant Date/Times
The Temporal.Instant
object represents a single point in time to the nearest nanosecond. It can be created from ISO 8601 formatted strings, or a number of seconds, milliseconds, or microseconds:
const
t1 = Temporal.Instant.from('2021-03-30T01:45:00+01:00[Europe/Berlin]'),
t2 = Temporal.Instant.from('2021-04-01T02:00+01:00'),
t3 = Temporal.Instant.fromEpochSeconds(1.0e8),
t4 = Temporal.Instant.fromEpochMilliseconds(1.0e10),
t5 = Temporal.Instant.epochNanoseconds(1.0e12);
Creating Zone-aware Date/Times
The Temporal.ZonedDateTime
object represents a timezone and calendar-aware date/time at the instant it occurred (or will occur) in a particular region. A variety of different constructors can be used:
new Temporal.ZonedDateTime(
1234567890000, // epoch nanoseconds
Temporal.TimeZone.from('America/Los_Angeles'), // timezone
Temporal.Calendar.from('iso8601') // default calendar
);
Temporal.ZonedDateTime.from('2025-12-07T03:24:30+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: 1,
day: 7,
hour: 9,
minute: 30,
second: 1,
millisecond: 2,
microsecond: 3,
nanosecond: 4
});
Creating Plain Dates and Times
It’s not always necessary to use exact moments, so the Temporal API provides objects which are independent of time zones. These could be used for simpler events, such as a meeting at 2pm today.
Temporal.PlainDateTime
refers to a calendar date and timeTemporal.PlainDate
refers to a specific calendar dateTemporal.PlainTime
refers to a specific time of dayTemporal.PlainYearMonth
refers to a date without a day component — such as “the April 2021 meeting”Temporal.PlainMonthDay
refers to a date without a year component — such as “Pi day is on March 14”.
All have similar constructors:
// create a new PlainDateTime
// both are 4 May 2021 at 1:14pm and 15 seconds
new Temporal.PlainDateTime(2021, 5, 4, 13, 14, 15);
Temporal.PlainDateTime.from('2021-05-04T13:14:15');
// create a new PlainDate
// both are 4 May, 2021
new Temporal.PlainDate(2021, 5, 4);
Temporal.PlainDate.from('2021-05-04');
// create a new PlainTime
// both are 1:14pm and 15 seconds
new Temporal.PlainTime(13, 14, 15);
Temporal.PlainTime.from('13:14:15');
// create a new year PlainYearMonth
// both are April 2021
new Temporal.PlainYearMonth(2021, 4);
Temporal.PlainYearMonth.from('2019-04');
// create a new PlainMonthDay
// both are 14 March
new Temporal.PlainMonthDay(3, 14);
Temporal.PlainMonthDay.from('03-14');
Extracting Values
All Temporal
objects can return discrete values about a specific date/time. For example, using a ZonedDateTime
:
const t1 = Temporal.ZonedDateTime.from('2025-12-07T03:24:30+02:00[Africa/Cairo]');
t1.year; // 2025
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
(1 for Monday to 7 for Sunday)dayOfYear
(1 to 365 or 366)weekOfYear
(1 to 52, or sometimes 53)daysInMonth
(28, 29, 30, or 31)daysInYear
(365 or 366)inLeapYear
(true
orfalse
)
Comparing and Sorting Dates
All Temporal
objects can be compared using a compare()
function, which returns an integer. For example, to compare two ZonedDateTime
objects:
// returns:
// -1 if t1 is before t2
// 0 if t1 and t2 are the same
// 1 is t1 is after t2
Temporal.ZonedDateTime.compare(t1, t2);
compare()
can be used as an Array sort()
function to arrange date/times 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 Calculations
Several methods are provided to perform date calculations on any Temporal object. All return a new Temporal of the same type when passed a Temporal.Duration
object, which defines a period in years
, months
, days
, hours
, and so on.
const t1 = Temporal.ZonedDateTime.from('2022-01-01T00:00:00+00:00[Europe/London]');
// add 8 hours 30 minutes
t1.add({ hours: 8, minutes: 30 });
// subtract 5 days
t1.subtract({ days: 5 });
// round to nearest month
t1.round({ smallestUnit: 'month' });
Note that Plain
dates and times can wrap. For example, adding 24 hours to any PlainTime
will return an object holding an identical value.
The until()
and since()
methods return a Temporal.Duration
object describing the time until or since a specific date/time:
// mounths until t1
t1.until().months;
// weeks since t1
t1.since().weeks;
Finally, the equals()
method can determine whether two date/time values are equivalent:
const
d1 = Temporal.PlainDate.from('2022-01-31');
d2 = Temporal.PlainDate.from('2021-01-31');
d1.equals(d2); // false
Formatting Dates With the Internationalization API
While not part of the Temporal API, the JavaScript Intl
(Internationalization) API provides a DateTimeFormat()
constructor which can be used to format Temporal or Date objects:
const d = new Temporal.PlainDate(2021, 3, 14);
// 3/14/2021
new Intl.DateTimeFormat('en-US').format(d);
// 14/3/2021
new Intl.DateTimeFormat('en-GB').format(d);
// miércoles, 14 de abril de 2021
new Intl.DateTimeFormat('es-ES', { dateStyle: 'full' }).format(d);
About Time?
The Date()
object has been a cause of developer frustration for a quarter of a century. While there’s no guarantee Temporal
will become a standard feature quickly, the future for JavaScript dates looks a little brighter.
You can try out Temporal
today, via an experimental polyfill, but don’t use it in production (yet)!
Further information:
- Temporal proposal documentation
- Temporal Cookbook — example usage recipes
Frequently Asked Questions (FAQs) about JavaScript Temporal API
What is the main difference between JavaScript Temporal API and the Date object?
The JavaScript Temporal API is a modern replacement for the Date object. The Date object has been a part of JavaScript since its inception, but it has several shortcomings, such as its inability to handle time zones and daylight saving time effectively. On the other hand, the Temporal API provides a comprehensive set of types that can handle dates, times, durations, and more, with a focus on accuracy and immutability. It also has built-in support for different calendars.
How does the Temporal API handle time zones?
The Temporal API has a dedicated type for handling time zones, called Temporal.TimeZone. This type allows you to convert between local and absolute time, taking into account daylight saving time and other factors. It also provides methods to get the current offset or the standard offset for a particular time zone.
Can I use the Temporal API with different calendars?
Yes, the Temporal API has built-in support for different calendars. Each Temporal type that deals with dates has a calendar property, which is an instance of Temporal.Calendar. This allows you to perform calculations and conversions that take into account the specific rules of the calendar.
How does the Temporal API handle durations?
The Temporal API has a Temporal.Duration type that represents a duration of time. This type provides methods to add, subtract, and compare durations, as well as to convert them to a string representation. It also supports different units of time, from nanoseconds to years.
What is the Temporal.PlainDate type?
The Temporal.PlainDate type represents a date without a time component. It provides methods to get and set the year, month, and day, as well as to add and subtract durations. It also supports comparisons and conversions to other types.
How can I format a Temporal object as a string?
The Temporal API provides a Temporal.Formatter type that can format Temporal objects as strings. You can specify the format using a pattern string, similar to the one used by the Intl.DateTimeFormat object.
Can I use the Temporal API in Node.js?
Yes, the Temporal API is a part of ECMAScript, the standard that JavaScript is based on, so it can be used in any JavaScript environment, including Node.js.
How does the Temporal API handle leap years?
The Temporal API takes into account leap years when performing calculations and conversions that involve dates. This is handled automatically by the Temporal types that deal with dates, such as Temporal.PlainDate and Temporal.PlainDateTime.
What is the Temporal.Now object?
The Temporal.Now object provides methods to get the current date, time, or date and time, either in the local time zone or in a specific time zone. It can also get the current system time as a Temporal.Instant.
How can I convert a Temporal object to a Date object?
The Temporal API provides methods to convert Temporal objects to Date objects. For example, you can use the Temporal.PlainDateTime.prototype.toDate method to convert a Temporal.PlainDateTime to a Date.
Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.