Updates:
Temporal.now
was renamed to Temporal.Now
.Instant
uses the ISO-8601 calendar. Listed the properties of some classes.Date
, JavaScript’s current date time API is infamously difficult to use. The ECMAScript proposal “Temporal” is a new and better date time API and currently at stage 3. It was created by Philipp Dunkel, Maggie Johnson-Pint, Matt Johnson-Pint, Brian Terlson, Shane Carr, Ujjwal Sharma, Philip Chimento, Jason Williams, and Justin Grant.
This blog post has two goals:
However, it is not an exhaustive documentation: For many details, you will have to consult the (excellent) documentation for Temporal.
Warning: These are my first explorations of this API – feedback welcome!
The Temporal date time API is accessible via the global variable Temporal
. It is a pleasure to use:
.toString()
can be used with much less consideration.Parts of this blog post:
Historically, how we measure time has progressed over the years:
Wall-clock time is the current time within a time zone (as shown by a clock on the wall). Wall-clock time is also called local time.
UTC, Z, and GMT are ways of specifying time that are similar, but subtly different:
UTC (Coordinated Universal Time) is the time standard that all times zones are based on. They are specified relative to it. That is, no country or territory has UTC as its local time zone.
Z (Zulu Time Zone) is a military time zone that is often used in aviation and the military as another name for UTC+0.
GMT (Greenwich Mean Time) is a time zone used in some European and African countries. It is UTC plus zero hours and therefore has the same time as UTC.
Sources:
Temporal’s time zones are based on the IANA Time Zone Database (short: tz database). IANA stands for Internet Assigned Numbers Authority. In that database, each time zone has an identifier and rules defining offsets for UTC times. If a time zone has standard time and daylight saving time, the offsets change during a year:
const standardTime = Temporal.ZonedDateTime.from({
timeZone: 'Europe/Zurich',
year: 1995,
month: 11,
day: 30,
hour: 3,
minute: 24,
});
assert.equal(
standardTime.toString(),
'1995-11-30T03:24:00+01:00[Europe/Zurich]'); // (A)
const daylightSavingTime = Temporal.ZonedDateTime.from({
timeZone: 'Europe/Zurich',
year: 1995,
month: 5,
day: 30,
hour: 3,
minute: 24,
});
assert.equal(
daylightSavingTime.toString(),
'1995-05-30T03:24:00+02:00[Europe/Zurich]'); // (B)
In standard time, the time offset for the Europe/Zurich
time zone is +1:00 (line A). In daylight saving time, the time offset is +2:00 (line B).
America/Los_Angeles
.The calendars supported by Temporal are based on the standard Unicode Unicode Common Locale Data Repository (CLDR) – among others:
buddhist
: Thai Buddhist calendarchinese
: Traditional Chinese calendarcoptic
: Coptic calendardangi
: Traditional Korean calendarethiopic
: Ethiopic calendar, Amete Mihret (epoch approx, 8 C.E.)gregory
: Gregorian calendarhebrew
: Traditional Hebrew calendarindian
: Indian calendarislamic
: Islamic calendariso8601
: ISO calendar (Gregorian calendar using the ISO-8601 calendar week rules)japanese
: Japanese Imperial calendarpersian
: Persian calendarroc
: Republic of China calendariso8601
is used by most western countries and gets extra support in Temporal, via methods such as Temporal.Now.zonedDateTimeISO()
(which returns the current date and wall-clock time in the system time zone and ISO-8601 calendar).
The standards ISO-8601 and RFC 3339 specify how to represent dates in strings. Currently, they are missing functionality that is needed and added by Temporal:
The goal is to eventually get these additions standardized (beyond ECMAScript).
Month-day syntax looks like this:
> Temporal.PlainMonthDay.from('12-24').toString()
'12-24'
The following code shows what a full date time string looks like. In practice, many of these parts will often be missing:
const zdt = Temporal.ZonedDateTime.from({
timeZone: 'Africa/Nairobi',
year: 2019,
month: 11,
day: 30,
hour: 8,
minute: 55,
second: 0,
millisecond: 123,
microsecond: 456,
nanosecond: 789,
});
assert.equal(
zdt.toString({calendarName: 'always', smallestUnit: 'nanosecond'}),
'2019-11-30T08:55:00.123456789+03:00[Africa/Nairobi][u-ca=iso8601]');
Parts of the date time string in the previous example:
'2019-11-30'
'-'
month '-'
day'T'
'08:55:00.123456789'
':'
minute ':'
seconds'.'
(separator between seconds and fractions of a second)'+03:00'
'Z'
which means '+0:00'
'[Africa/Nairobi]'
'[u-ca=iso8601]'
The last two items are not currently standardized.
Temporal distinguishes two kinds of time. Given a global instant of time:
Epoch time is one way of representing exact time: It’s a number counting time units (such as nanoseconds) before or since Unix epoch (midnight UTC on January 1, 1970).
Let’s first take a quick look at Temporal’s core classes and what data goes into them. They are covered in more detail later.
ZonedDateTime
: new Temporal.ZonedDateTime(epochNanoseconds: bigint, timeZone: TimeZoneLike, calendar?: CalendarLike)
Instant
: new Temporal.Instant(epochNanoseconds : bigint)
PlainDateTime
: new Temporal.PlainDateTime(isoYear: number, isoMonth: number, isoDay: number, isoHour: number = 0, isoMinute: number = 0, isoSecond: number = 0, isoMillisecond: number = 0, isoMicrosecond: number = 0, isoNanosecond: number = 0, calendar?: CalendarLike)
PlainDate
: new Temporal.PlainDate(isoYear: number, isoMonth: number, isoDay: number, calendar?: CalendarLike)
PlainTime
: new Temporal.PlainTime(isoHour: number = 0, isoMinute: number = 0, isoSecond: number = 0, isoMillisecond: number = 0, isoMicrosecond: number = 0, isoNanosecond: number = 0)
PlainYearMonth
: new Temporal.PlainYearMonth(isoYear: number, isoMonth: number, calendar?: CalendarLike, referenceISODay: number = 1)
PlainMonthDay
: new Temporal.PlainMonthDay(isoMonth: number, isoDay: number, calendar?: CalendarLike, referenceISOYear?: number)
Duration
: new Temporal.Duration(years?: number, months?: number, weeks?: number, days?: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number, microseconds?: number, nanoseconds?: number)
There are two main ways of creating instances of Temporal classes.
On one hand, we can create instances via constructors. Each constructor accepts the minimal amount of data needed to fully specify an instance. For example, in the case of the two classes for exact time, Instant
and ZonedDateTime
, the point in time itself is specified via epoch nanoseconds.
const epochNanoseconds = 6046761644163000000n;
const timeZone = 'America/Los_Angeles'; // San Francisco
const zdt1 = new Temporal.ZonedDateTime(epochNanoseconds, timeZone);
assert.equal(
zdt1.toString(),
'2161-08-12T09:00:44.163-07:00[America/Los_Angeles]');
.from()
On the other hand, we can create instances via the static factory method .from()
. It is overloaded: Most classes support three kinds of values for its parameter.
First, if the parameter is an instance of the same class, then that instance is cloned:
const zdt2 = Temporal.ZonedDateTime.from(zdt1);
assert.equal(
zdt2.toString(),
'2161-08-12T09:00:44.163-07:00[America/Los_Angeles]');
// Really a clone?
assert.notEqual(zdt1, zdt2);
Second, all other objects are interpreted as specifying various fields with time-related information:
const zdt3 = Temporal.ZonedDateTime.from({
timeZone: 'America/Los_Angeles',
year: 2161,
month: 8,
day: 12,
hour: 9,
minute: 0,
second: 44,
millisecond: 163,
microsecond: 0,
nanosecond: 0,
});
assert.equal(
zdt3.toString(),
'2161-08-12T09:00:44.163-07:00[America/Los_Angeles]');
Third, all primitive values are coerced to string and parsed:
const zdt4 = Temporal.ZonedDateTime.from(
'2161-08-12T09:00:44.163[America/Los_Angeles]'); // (A)
assert.equal(
zdt4.toString(),
'2161-08-12T09:00:44.163-07:00[America/Los_Angeles]'); // (B)
Note that we didn’t need to specify the offset in line A, but it is shown in line B.
The fields we use when creating an instance via .from()
become properties of that instance:
const zonedDateTime = Temporal.ZonedDateTime.from({
timeZone: 'Africa/Lagos',
year: 1995,
month: 12,
day: 7,
hour: 3,
minute: 24,
second: 30,
millisecond: 0,
microsecond: 3,
nanosecond: 500,
});
assert.equal(
zonedDateTime.toString(),
'1995-12-07T03:24:30.0000035+01:00[Africa/Lagos]');
assert.equal(
zonedDateTime.year, 1995);
assert.equal(
zonedDateTime.month, 12);
assert.equal(
zonedDateTime.dayOfWeek, 4);
assert.equal(
zonedDateTime.epochNanoseconds, 818303070000003500n);
These properties are immutable: If we want to change them, we have to create a new instance where they have different values. Method .with()
lets us do that:
const newZonedDateTime = zonedDateTime.with({
year: 2222,
month: 3,
});
assert.equal(
newZonedDateTime.toString(),
'2222-03-07T03:24:30.0000035+01:00[Africa/Lagos]');
TimeZone
, Calendar
, Duration
, etc.) Whenever Temporal needs an instance of a class C
, it accepts any value that is “like” an instance of class C
:
C
C.from()
C
.C.from()
Values like TimeZone
– these are three ways of specifying time zones (last arguments of the following constructor invocations):
const zdt1 = new Temporal.ZonedDateTime(0n,
new Temporal.TimeZone('America/Lima'));
const zdt2 = new Temporal.ZonedDateTime(0n,
{timeZone: 'America/Lima'});
const zdt3 = new Temporal.ZonedDateTime(0n,
'America/Lima');
Values like Calendar
– these are three ways of specifying calendars (last arguments of the following constructor invocations):
const pd1 = new Temporal.PlainDate(1992, 2, 24,
new Temporal.Calendar('iso8601'));
const pd2 = new Temporal.PlainDate(1992, 2, 24,
{calendar: 'iso8601'});
const pd3 = new Temporal.PlainDate(1992, 2, 24,
'iso8601');
Values like Duration
– these are three ways of specifying durations (argument of .add()
):
const pdStart = Temporal.PlainDate.from('2022-03-08');
const pd1 = pdStart.add(
Temporal.Duration.from({years: 5, months: 2, days: 1}));
assert.equal(pd1.toString(), '2027-05-09');
const pd2 = pdStart.add(
{years: 5, months: 2, days: 1});
assert.equal(pd2.toString(), '2027-05-09');
const pd3 = pdStart.add(
'P5Y2M1D');
assert.equal(pd3.toString(), '2027-05-09');
Temporal.Now
: the current time The object Temporal.Now
has several factory methods for creating Temporal values representing the current time:
> Temporal.Now.instant().toString()
'2021-06-27T12:51:10.961Z'
> Temporal.Now.zonedDateTimeISO('Asia/Shanghai').toString()
'2021-06-27T20:51:10.961+08:00[Asia/Shanghai]'
> Temporal.Now.plainDateTimeISO().toString()
'2021-06-27T20:51:10.961'
> Temporal.Now.plainTimeISO().toString()
'20:51:10.961'
Properties of Temporal.Now
:
.timeZone()
.instant()
.plainDateTime(calendar, temporalTimeZoneLike?)
.plainDateTimeISO(temporalTimeZoneLike?)
.zonedDateTime(calendar, temporalTimeZoneLike?)
.zonedDateTimeISO(temporalTimeZoneLike?)
.plainDate(calendar, temporalTimeZoneLike?)
.plainDateISO(temporalTimeZoneLike?)
.plainTimeISO(temporalTimeZoneLike?)
These properties are documented here.
We can use Temporal.Now
to access the current time zone of the system. This time zone can change – for example, when the system travels:
> Temporal.Now.timeZone().toString()
'Asia/Shanghai'
The concept of a “current calendar” is more complicated. Ideas for how to best handle it are still evolving. This is the current way of getting the ID (a string) of the “preferred calendar”:
const preferredCalendarId = (new Intl.DateTimeFormat())
.resolvedOptions().calendar;
assert.equal(preferredCalendarId, 'gregory');
Instant
, class ZonedDateTime
, nanoseconds since epoch Temporal represents exact time in three ways:
Instant
(UTC time).ZonedDateTime
(wall-clock time plus a time zone and a calendar).Instant
Class Instant
represents global exact time. Its time standard is UTC. It is mostly a container for nanoseconds since epoch. That is also reflected by it not having properties such as .year
and .hour
(which ZonedDateTime
and PlainDateTime
have).
For some operations (such as .toString()
), Instant
internally uses an ISO-8601 calendar, but that calendar is not stored in instances.
Use case:
const instant = Temporal.Now.instant();
assert.equal(
instant.toString(),
'2021-06-27T08:32:33.18174345Z');
Properties of Instant
:
.from(item)
.fromEpochSeconds(epochSeconds)
.fromEpochMilliseconds(epochMilliseconds)
.fromEpochMicroseconds(epochMicroseconds)
.fromEpochNanoseconds(epochNanoseconds)
.compare(one, two)
Properties of Instant.prototype
:
get .epochSeconds
get .epochMilliseconds
get .epochMicroseconds
get .epochNanoseconds
.add(temporalDurationLike)
.subtract(temporalDurationLike)
.until(other, options?)
.since(other, options?)
.round(options)
.equals(other)
.toString(options?)
.toLocaleString(locales?, options?)
.toJSON()
.valueOf()
.toZonedDateTime(item)
.toZonedDateTimeISO(item)
These properties are documented here.
ZonedDateTime
Class ZonedDateTime
represents time via wall-clock time plus a time zone and a calendar.
Use cases for this class:
// Current time in Melbourne, Australia (in ISO-8601 calendar)
const zonedDateTime = Temporal.Now.zonedDateTimeISO(
'Australia/Melbourne');
assert.equal(
zonedDateTime.toString(),
'2021-06-27T10:46:31.179753181+10:00[Australia/Melbourne]');
Properties of ZonedDateTime
:
.from(item, options?)
.compare(one, two)
Properties of ZonedDateTime.prototype
:
get .calendar
get .timeZone
get .year
get .month
get .monthCode
get .day
get .hour
get .minute
get .second
get .millisecond
get .microsecond
get .nanosecond
get .epochSeconds
get .epochMilliseconds
get .epochMicroseconds
get .epochNanoseconds
get .dayOfWeek
get .dayOfYear
get .weekOfYear
get .hoursInDay
get .daysInWeek
get .daysInMonth
get .daysInYear
get .monthsInYear
get .inLeapYear
get .offsetNanoseconds
get .offset
.with(temporalZonedDateTimeLike, options?)
.withPlainTime(plainTimeLike?)
.withPlainDate(plainDateLike)
.withTimeZone(timeZoneLike)
.withCalendar(calendarLike)
.add(temporalDurationLike, options?)
.subtract(temporalDurationLike, options?)
.until(other, options?)
.since(other, options?)
.round(options)
.equals(other)
.toString(options?)
.toLocaleString(locales?, options?)
.toJSON()
.valueOf()
.startOfDay()
.toInstant()
.toPlainDate()
.toPlainTime()
.toPlainDateTime()
.toPlainYearMonth()
.toPlainMonthDay()
.getISOFields()
These properties are documented here.
PlainDateTime
, PlainDate
, PlainTime
If a class doesn’t have a time zone, Temporal calls it “plain”. There are three timezone-less classes: PlainDateTime
, PlainDate
, and PlainTime
. They are abstract representations of time.
Use cases for these classes:
const zonedDateTime = Temporal.Now.zonedDateTimeISO(
'Asia/Novosibirsk');
assert.equal(
zonedDateTime.toString(),
'2021-06-27T10:46:31.179+07:00[Asia/Novosibirsk]');
// Get the wall-clock time as a string
const plainDateTime = zonedDateTime.toPlainDateTime()
assert.equal(
plainDateTime.toString(),
'2021-06-27T10:46:31.179');
Properties of PlainDateTime
:
.from(item, options?)
.compare(one, two)
Properties of PlainDateTime.prototype
:
get .calendar
get .year
get .month
get .monthCode
get .day
get .hour
get .minute
get .second
get .millisecond
get .microsecond
get .nanosecond
get .dayOfWeek
get .dayOfYear
get .weekOfYear
get .daysInWeek
get .daysInMonth
get .daysInYear
get .monthsInYear
get .inLeapYear
.with(temporalDateTimeLike, options?)
.withPlainTime(plainTimeLike?)
.withPlainDate(plainDateLike)
.withCalendar(calendar)
.add(temporalDurationLike, options?)
.subtract(temporalDurationLike, options?)
.until(other, options?)
.since(other, options?)
.round(options)
.equals(other)
.toString(options?)
.toLocaleString(locales?, options?)
.toJSON()
.valueOf()
.toZonedDateTime(temporalTimeZoneLike, options?)
.toPlainDate()
.toPlainYearMonth()
.toPlainMonthDay()
.toPlainTime()
.getISOFields()
These properties are documented here.
PlainDate
and PlainTime
have subsets of PlainDateTime
’s properties.
PlainYearMonth
An instance of PlainYearMonth
abstractly refers to a particular month in a particular year.
Use case:
const plainYearMonth = Temporal.PlainYearMonth.from(
{year: 2022, month: 10});
assert.equal(
plainYearMonth.toString(),
'2022-10');
PlainMonthDay
An instance of PlainMonthDay
abstractly refers to a particular day in a particular month.
Use case:
// Bastille Day
const bastilleDay = Temporal.PlainMonthDay.from({month: 7, day: 14});
assert.equal(
bastilleDay.toString(),
'07-14');
// Bastille Day in 1989 in Paris
const zonedDateTime = bastilleDay
.toPlainDate({year: 1989})
.toZonedDateTime('Europe/Paris');
assert.equal(
zonedDateTime.toString(),
'1989-07-14T00:00:00+02:00[Europe/Paris]');
Calendar
All Temporal classes that contain full dates use calendars to help them with various computations. Most code will use the ISO-8601 calendar, but other calendar systems are supported, too.
const calendar1 = new Temporal.Calendar('iso8601');
const calendar2 = Temporal.Calendar.from('iso8601');
const calendar3 = Temporal.Calendar.from({calendar: 'iso8601'});
TimeZone
Instances of TimeZone
represent time zones. They support IANA time zones, UTC, and UTC offsets. For most use cases, IANA time zones are the best choice because they enable proper handling of daylight saving time.
const timeZone1 = new Temporal.TimeZone('America/Nuuk');
const timeZone2 = Temporal.TimeZone.from('America/Nuuk');
const timeZone3 = Temporal.TimeZone.from({timeZone: 'America/Nuuk'});
Duration
A duration represents a length of time – for example, 3 hours and 45 minutes.
Durations are used for temporal arithmetic:
const duration = Temporal.Duration.from({hours: 3, minutes: 45});
assert.equal(
duration.total({unit: 'second'}),
13500);
Note that there is no simple normalization for durations:
The former should not be automatically converted to the latter.
Method .toString()
of duration objects returns strings that conform to the ISO-8601 notation for durations:
// Date information
assert.equal(
Temporal.Duration.from(
{years: 1, months: 2, weeks: 3, days: 4}).toString(),
'P1Y2M3W4D');
// Time information
assert.equal(
Temporal.Duration.from(
{hours: 1, minutes: 2, seconds: 3, milliseconds: 4}).toString(),
'PT1H2M3.004S');
// Mixed information
assert.equal(
Temporal.Duration.from(
{days: 30, hours: 50}).toString(),
'P30DT50H');
// No duration
assert.equal(
Temporal.Duration.from(
{hours: 0}).toString(),
'PT0S');
Observations:
'P'
.'T'
.The static factory method .from()
always accepts strings:
const zdt = Temporal.ZonedDateTime.from(
'2019-12-01T12:00:00[Pacific/Auckland]');
The .toString()
method works predictably and can be configured:
assert.equal(
zdt.toString(),
'2019-12-01T12:00:00+13:00[Pacific/Auckland]');
assert.equal(
zdt.toString({offset: 'never', timeZoneName: 'never'}),
'2019-12-01T12:00:00');
assert.equal(
zdt.toString({smallestUnit: 'minute'}),
'2019-12-01T12:00+13:00[Pacific/Auckland]');
However, .toString()
doesn’t let you hide minutes in this case – you have to convert the ZonedDateTime
to a PlainDate
if that is what you want:
assert.equal(
zdt.toPlainDate().toString(),
'2019-12-01');
All Temporal date time values have a .toJSON()
method and can therefore be stringified to JSON:
const zdt = Temporal.ZonedDateTime.from(
'2019-12-01T12:00[Asia/Singapore]');
// Stringifying a zoned date time directly:
assert.equal(
JSON.stringify(zdt),
'"2019-12-01T12:00:00+08:00[Asia/Singapore]"');
// Stringifying a zoned date time inside an object:
const obj = {startTime: zdt};
assert.equal(
JSON.stringify(obj),
'{"startTime":"2019-12-01T12:00:00+08:00[Asia/Singapore]"}');
If you want to parse JSON with date time values, you need to set up a JSON reviver.
Temporal’s support for converting date time values to human readable strings is similar to Intl.DateTimeFormat
’s:
const zdt = Temporal.ZonedDateTime.from(
'2019-12-01T12:00[Europe/Berlin]');
assert.equal(
zdt.toLocaleString(),
'12/1/2019, 12:00:00 PM GMT+1');
assert.equal(
zdt.toLocaleString('de-DE'),
'1.12.2019, 12:00:00 MEZ');
assert.equal(
zdt.toLocaleString('en-GB', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
}),
'Sunday, 1 December 2019');
Temporal does not support parsing human-readable strings.
Date
and Temporal
On one hand, we can convert legacy dates to Temporal instants:
const legacyDate = new Date('1970-01-01T00:00:01Z');
const instant1 = legacyDate.toTemporalInstant();
assert.equal(
instant1.toString(),
'1970-01-01T00:00:01Z');
This is an alternative to the previous approach:
const ms = legacyDate.getTime();
const instant2 = Temporal.Instant.fromEpochMilliseconds(ms);
assert.equal(
instant2.toString(),
'1970-01-01T00:00:01Z');
On the other hand, one of the fields exposed by Instant
provides us with the epoch time in milliseconds – which we can use to create a date:
const instant = Temporal.Instant.from('1970-01-01T00:00:01Z');
const legacyDate = new Date(instant.epochMilliseconds);
assert.equal(
legacyDate.toISOString(),
'1970-01-01T00:00:01.000Z');
Every date time class D
provides a function D.compare
for sorting instances of D
:
const dates = [
Temporal.ZonedDateTime.from('2022-12-01T12:00[Asia/Tehran]'),
Temporal.ZonedDateTime.from('2001-12-01T12:00[Asia/Tehran]'),
Temporal.ZonedDateTime.from('2009-12-01T12:00[Asia/Tehran]'),
];
dates.sort(Temporal.ZonedDateTime.compare);
assert.deepEqual(
dates.map(d => d.toString()),
[
'2001-12-01T12:00:00+03:30[Asia/Tehran]',
'2009-12-01T12:00:00+03:30[Asia/Tehran]',
'2022-12-01T12:00:00+03:30[Asia/Tehran]',
]);
D.compare()
also accepts strings – if they can be parsed via D.from()
:
const dates = [
'2022-12-01T12:00[Asia/Tehran]',
'2001-12-01T12:00[Asia/Tehran]',
'2009-12-01T12:00[Asia/Tehran]',
];
dates.sort(Temporal.ZonedDateTime.compare);
assert.deepEqual(
dates,
[
'2001-12-01T12:00[Asia/Tehran]',
'2009-12-01T12:00[Asia/Tehran]',
'2022-12-01T12:00[Asia/Tehran]',
]);
Instant
to ZonedDateTime
and PlainDateTime
const instant = Temporal.Instant.from('1970-01-01T00:00:01Z');
const zonedDateTime = instant.toZonedDateTimeISO('Europe/Madrid');
assert.equal(
zonedDateTime.toString(),
'1970-01-01T01:00:01+01:00[Europe/Madrid]');
const plainDateTime1 = zonedDateTime.toPlainDateTime();
assert.equal(
plainDateTime1.toString(),
'1970-01-01T01:00:01');
const timeZone = Temporal.TimeZone.from('Europe/Madrid');
const plainDateTime2 = timeZone.getPlainDateTimeFor(instant);
assert.equal(
plainDateTime2.toString(),
'1970-01-01T01:00:01');
ZonedDateTime
to Instant
and PlainDateTime
const zonedDateTime = Temporal.ZonedDateTime.from(
'2019-12-01T12:00[Europe/Minsk]');
const instant = zonedDateTime.toInstant();
assert.equal(
instant.toString(),
'2019-12-01T09:00:00Z');
const plainDateTime = zonedDateTime.toPlainDateTime();
assert.equal(
plainDateTime.toString(),
'2019-12-01T12:00:00');
PlainDateTime
to ZonedDateTime
and Instant
const plainDateTime = Temporal.PlainDateTime.from(
'1995-12-07T03:24:30');
const zonedDateTime = plainDateTime.toZonedDateTime('Europe/Berlin');
assert.equal(
zonedDateTime.toString(),
'1995-12-07T03:24:30+01:00[Europe/Berlin]');
const instant = zonedDateTime.toInstant();
assert.equal(
instant.toString(),
'1995-12-07T02:24:30Z');
const source = Temporal.ZonedDateTime.from(
'2022-01-09T02:00[America/Chicago]');
const target = source.withTimeZone('America/Anchorage');
assert.equal(
target.toString(),
'2022-01-08T23:00:00-09:00[America/Anchorage]');
const departure = Temporal.ZonedDateTime.from(
'2017-05-08T12:55[Europe/Berlin]'); // Munich
const arrival = Temporal.ZonedDateTime.from(
'2017-05-08T17:10[America/Los_Angeles]'); // Seattle
const flightTime = departure.until(arrival);
assert.equal(
flightTime.toString(), 'PT13H15M');
const plainDate = Temporal.PlainDate.from('2022-03-08');
assert.equal(
plainDate.add({days: 1}).toString(),
'2022-03-09');
To compute Labor Day (first Monday in September) for a given year, we need to figure out how many days to add to September 1 in order to get to weekday 1 (Monday).
const mod = (a, b) => ((a % b) + b) % b;
function getLaborDay(year) {
const firstOfSeptember = Temporal.PlainDate.from({
year,
month: 9,
day: 1,
});
// How many days until Monday?
const MONDAY = 1;
const daysToAdd = mod(MONDAY - firstOfSeptember.dayOfWeek, 7);
return firstOfSeptember.add({days: daysToAdd});
}
assert.equal(
getLaborDay(2021).toString(),
'2021-09-06');
assert.equal(
getLaborDay(2022).toString(),
'2022-09-05');
The “Can I use” page for Temporal shows on which platforms the API is supported.
For now, the proposal warns:
Although this proposal's API is not expected to change, implementers of this proposal MUST NOT ship unflagged Temporal implementations until IETF standardizes timezone/calendar string serialization formats. See #1450 for updates.
The proposal has a list of polyfills for the Temporal API.
Temporal
and Date
Date
API is documented in a chapter in the book “JavaScript for impatient programmers”.