Temporal.ZonedDateTime

Table of Contents

A Temporal.ZonedDateTime is a timezone-aware, calendar-aware date/time type that represents a real event that has happened (or will happen) at a particular instant from the perspective of a particular region on Earth. As the broadest Temporal type, Temporal.ZonedDateTime can be considered a combination of Temporal.TimeZone, Temporal.Instant, and Temporal.PlainDateTime (which includes Temporal.Calendar).

As the only Temporal type that persists a time zone, Temporal.ZonedDateTime is optimized for use cases that require a time zone:

A Temporal.ZonedDateTime instance can be losslessly converted into every other Temporal type except Temporal.Duration. Temporal.Instant, Temporal.PlainDateTime, Temporal.PlainDate, Temporal.PlainTime, Temporal.PlainYearMonth, and Temporal.PlainMonthDay all carry less information and can be used when complete information is not required.

The Temporal.ZonedDateTime API is a superset of Temporal.PlainDateTime, which makes it easy to port code back and forth between the two types as needed. Because Temporal.PlainDateTime is not aware of time zones, in use cases where the time zone is known it's recommended to use Temporal.ZonedDateTime which will automatically adjust for DST and can convert easily to Temporal.Instant without having to re-specify the time zone.

Constructor

new Temporal.ZonedDateTime(epochNanoseconds: bigint, timeZone: string | object, calendar?: string | object) : Temporal.ZonedDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object.

Like all Temporal constructors, this constructor is an advanced API used to create instances for a narrow set of use cases. Instead of the constructor, Temporal.ZonedDateTime.from() is preferred instead because it accepts more kinds of input and provides options for handling ambiguity and overflow.

The range of allowed values for this type is the same as the old-style JavaScript Date: 100 million (108) days before or after the Unix epoch. This range covers approximately half a million years. If epochNanoseconds is outside of this range, a RangeError will be thrown.

Usage examples:

// UNIX epoch in California
new Temporal.ZonedDateTime(0n, Temporal.TimeZone.from('America/Los_Angeles'), Temporal.Calendar.from('iso8601'));
  // => 1969-12-31T16:00:00-08:00[America/Los_Angeles]
new Temporal.ZonedDateTime(0n, 'America/Los_Angeles');
  // => 1969-12-31T16:00:00-08:00[America/Los_Angeles]
  // same, but shorter

Static methods

Temporal.ZonedDateTime.from(thing: any, options?: object) : Temporal.ZonedDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object.

This static method creates a new Temporal.ZonedDateTime object from another value. If the value is another Temporal.ZonedDateTime object, a new but otherwise identical object will be returned. If the value is any other object, a Temporal.ZonedDateTime will be constructed from the values of any year (or era and eraYear), month (or monthCode), day, hour, minute, second, millisecond, microsecond, nanosecond, and/or calendar properties that are present. At least the timeZone, year (or era and eraYear), month (or monthCode), and day properties must be present. Other properties are optional. If calendar is missing, it will be assumed to be Temporal.Calendar.from('iso8601'). Any other missing properties will be assumed to be 0 (for time fields).

Date/time values will be interpreted in context of the provided offset and/or time zone, depending on the offset option.

Date/time values in object inputs will be interpreted in the context of calendar. However, date/time values in string inputs are always interpreted in the context of the ISO 8601 calendar.

Any non-object value is converted to a string, which is expected to be an ISO 8601 string that includes a time zone ID in brackets, and an optional calendar. For example:

2020-08-05T20:06:13+09:00[Asia/Tokyo][u-ca=japanese]

If the string isn't valid, then a RangeError will be thrown regardless of the value of overflow.

Note that this string format (albeit limited to the ISO calendar system) is also used by java.time and some other time-zone-aware libraries. For more information on Temporal's extensions to the ISO string format and the progress towards becoming a published standard, see ISO standard extensions.

The time zone ID is always required. 2020-08-05T20:06:13+09:00 and 2020-08-05T11:06:13Z are not valid inputs to this method because they don't include a time zone ID in square brackets. To parse these string formats, use Temporal.Instant:

Temporal.Instant.from('2020-08-05T20:06:13+0900').toZonedDateTimeISO('Asia/Tokyo');

Usually a named IANA time zone like Europe/Paris or America/Los_Angeles is used, but there are cases where adjusting for DST or other time zone offset changes is not desired. For these cases, non-DST-adjusting, single-offset time zones are available, e.g. Etc/GMT-14 through Etc/GMT+12. For historical reasons, signs are reversed between these time zones' names and their offsets. For example, Etc/GMT+8 would be used for cases where the UTC offset is always -08:00, e.g. ocean shipping off the coast of California. If a non-whole-hour single-offset time zone is needed, the offset can be used as the time zone ID of an offset time zone.

Temporal.Instant.from('2020-08-05T20:06:13+05:45[+05:45]');
// OR
Temporal.Instant.from('2020-08-05T20:06:13+05:45').toZonedDateTimeISO('+05:45');
// => 2020-08-05T20:06:13+05:45[+05:45]

Note that using Temporal.ZonedDateTime with a single-offset time zone will not adjust for Daylight Saving Time or other time zone changes. Therefore, using offset time zones with Temporal.ZonedDateTime is relatively unusual. Instead of using Temporal.ZonedDateTime with an offset time zone, it may be easier for most use cases to use Temporal.PlainDateTime and/or Temporal.Instant instead.

The overflow option works as follows, if thing is an object:

The overflow option is ignored if thing is a string.

Additionally, if the result is earlier or later than the range of dates that Temporal.PlainDateTime can represent (approximately half a million years centered on the Unix epoch), then this method will throw a RangeError regardless of overflow.

NOTE: Although Temporal does not deal with leap seconds, dates coming from other software may have a second value of 60. In the default 'constrain' mode and when parsing an ISO 8601 string, this will be converted to 59. In 'reject' mode, this function will throw, so if you have to interoperate with times that may contain leap seconds, don't use reject.

If the input contains a time zone offset, in rare cases it's possible for those values to conflict for a particular local date and time. For example, this could happen if the definition of a time zone is changed (e.g. to abolish DST) after storing a Temporal.ZonedDateTime as a string representing a far-future event. If the time zone and offset are in conflict, then the offset option is used to resolve the conflict:

An example of why offset is needed is Brazil which permanently stopped using DST in 2019. This change meant that previously-stored values for 2020 and beyond might now be ambiguous. For details about problems like this and how to solve them with offset, see Ambiguity Caused by Permanent Changes to a Time Zone Definition.

The offset option is ignored if an offset is not present in the input. In that case, the time zone and the disambiguation option are used to convert date/time values to exact time.

The disambiguation option controls what time zone offset is used when the input time is ambiguous (as in the repeated clock hour after DST ends) or invalid due to offset changes skipping clock time (as in the skipped clock hour after DST starts):

When interoperating with existing code or services, 'compatible' mode matches the behavior of legacy Date as well as libraries like moment.js, Luxon, and date-fns. This mode also matches the behavior of cross-platform standards like RFC 5545 (iCalendar).

During "skipped" clock time like the hour after DST starts, this method interprets invalid times using the pre-transition time zone offset if 'compatible' or 'later' is used or the post-transition time zone offset if 'earlier' is used. This behavior avoids exceptions when converting non-existent local time values to Temporal.ZonedDateTime.

For usage examples and a more complete explanation of how this disambiguation works and why it is necessary, see Resolving Ambiguity.

The disambiguation option is only used if there is no offset in the input, or if the offset is ignored by using the offset option as described above. If the offset in the input is used, then there is no ambiguity and the disambiguation option is ignored.

NOTE: The allowed values for the thing.month property start at 1, which is different from legacy Date where months are represented by zero-based indices (0 to 11).

Example usage:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30+02:00[Africa/Cairo]');
zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30+02:00[Africa/Cairo][u-ca=islamic]');
/* WRONG */ zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30');  // => throws RangeError: time zone ID required
/* WRONG */ zdt = Temporal.ZonedDateTime.from('1995-12-07T01:24:30Z');  // => throws RangeError: time zone ID required
/* WRONG */ zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30+02:00');  // => throws RangeError: time zone ID required
zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30+02:00[+02:00]');  // OK (offset time zone) but rarely used
/* WRONG */ zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30+03:00[Africa/Cairo]');
  // => RangeError: Offset is invalid for '1995-12-07T03:24:30' in 'Africa/Cairo'. Provided: +03:00, expected: +02:00.

zdt = Temporal.ZonedDateTime.from({
    timeZone: 'America/Los_Angeles',
    year: 1995,
    month: 12,
    day: 7,
    hour: 3,
    minute: 24,
    second: 30,
    millisecond: 0,
    microsecond: 3,
    nanosecond: 500
});  // => 1995-12-07T03:24:30.0000035-08:00[America/Los_Angeles]

// Different overflow modes
zdt = Temporal.ZonedDateTime.from({ timeZone: 'Europe/Paris', year: 2001, month: 13, day: 1 }, { overflow: 'constrain' })
  // => 2001-12-01T00:00:00+01:00[Europe/Paris]
zdt = Temporal.ZonedDateTime.from({ timeZone: 'Europe/Paris', year: 2001, month: 13, day: 1 }, { overflow: 'reject' })
  // => throws RangeError

Temporal.ZonedDateTime.compare(one: Temporal.ZonedDateTime, two: Temporal.ZonedDateTime) : number

Parameters:

Returns: an integer indicating whether one comes before or after or is equal to two.

This function can be used to sort arrays of Temporal.ZonedDateTime objects.

Comparison will use exact time, not clock time, because sorting is almost always based on when events happened in the real world. Note that during the hour before and after DST ends, sorting of clock time may not match the order the events actually occurred.

Note that this function will not return 0 if the two objects have different calendar or timeZone properties, even if the exact timestamps are equal. If exact timestamps are equal, then .calendar.id will be compared lexicographically, in order to ensure a deterministic sort order. If those are equal too, then .timeZone.id will be compared lexicographically.

For example:

arr = [
  Temporal.ZonedDateTime.from('2020-02-01T12:30-05:00[America/Toronto]'),
  Temporal.ZonedDateTime.from('2020-02-01T12:30-05:00[America/New_York]'),
  Temporal.ZonedDateTime.from('2020-02-01T12:30+01:00[Europe/Brussels]'),
  Temporal.ZonedDateTime.from('2020-02-01T12:30+00:00[Europe/London]')
];
sorted = arr.sort(Temporal.ZonedDateTime.compare);
JSON.stringify(sorted, undefined, 2);
// =>
// '[
//   "2020-02-01T12:30+01:00[Europe/Brussels]",
//   "2020-02-01T12:30+00:00[Europe/London]",
//   "2020-02-01T12:30-05:00[America/New_York]",
//   "2020-02-01T12:30-05:00[America/Toronto]"
// ]'

Note that in unusual cases like the repeated clock hour after DST ends, values that are later in the real world can be earlier in clock time, or vice versa. To sort Temporal.ZonedDateTime values according to clock time only (which is a very rare use case), convert each value to Temporal.PlainDateTime. For example:

one = Temporal.ZonedDateTime.from('2020-11-01T01:45-07:00[America/Los_Angeles]');
two = Temporal.ZonedDateTime.from('2020-11-01T01:15-08:00[America/Los_Angeles]');
Temporal.ZonedDateTime.compare(one, two);
  // => -1
  // (because `one` is earlier in the real world)
Temporal.PlainDateTime.compare(one.toPlainDateTime(), two.toPlainDateTime());
  // => 1
  // (because `one` is later in clock time)
Temporal.Instant.compare(one.toInstant(), two.toInstant());
  // => -1
  // (because `Temporal.Instant` and `Temporal.ZonedDateTime` both compare real-world exact times)

Properties

zonedDateTime.year : number

zonedDateTime.month : number

zonedDateTime.day : number

zonedDateTime.hour: number

zonedDateTime.minute: number

zonedDateTime.second: number

zonedDateTime.millisecond: number

zonedDateTime.microsecond: number

zonedDateTime.nanosecond: number

The above read-only properties allow accessing each component of a date or time individually.

Date unit details:

Either month or monthCode can be used in from or with to refer to the month. Similarly, in calendars that user eras an era/eraYear pair can be used in place of year when calling from or with.

Time unit details:

Usage examples:

dt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30.000003500[Europe/Rome]');
dt.year;        // => 1995
dt.month;       // => 12
dt.monthCode;   // => 'M12'
dt.day;         // => 7
dt.hour;        // => 3
dt.minute;      // => 24
dt.second;      // => 30
dt.millisecond; // => 0
dt.microsecond; // => 3
dt.nanosecond;  // => 500

dt = Temporal.ZonedDateTime.from('2019-02-23T03:24:30.000003500[Europe/Rome][u-ca=hebrew]');
dt.year;        // => 5779
dt.month;       // => 6
dt.monthCode;   // => 'M05L'
dt.day;         // => 18
dt.hour;        // => 3
dt.minute;      // => 24
dt.second;      // => 30
dt.millisecond; // => 0
dt.microsecond; // => 3
dt.nanosecond;  // => 500

NOTE: The possible values for the month property start at 1, which is different from legacy Date where months are represented by zero-based indices (0 to 11).

zonedDateTime.epochSeconds: number

zonedDateTime.epochMilliseconds: number

zonedDateTime.epochMicroseconds: bigint

zonedDateTime.epochNanoseconds: bigint

The above read-only properties return the integer number of full seconds, milliseconds, microseconds, or nanoseconds between zonedDateTime and 00:00 UTC on 1970-01-01, otherwise known as the UNIX Epoch.

These properties are equivalent to zonedDateTime.toInstant().epochSeconds, zonedDateTime.toInstant().epochMilliseconds, zonedDateTime.toInstant().epochMicroseconds, zonedDateTime.toInstant().epochNanoseconds, respectively. Any fractional remainders are truncated towards zero. The time zone is irrelevant to these properties because time because there is only one epoch, not one per time zone.

Note that the epochSeconds and epochMilliseconds properties are of type number (although only integers are returned) while the epochMicroseconds and epochNanoseconds are of type bigint.

The epochMilliseconds property is the easiest way to construct a legacy Date object from a Temporal.ZonedDateTime instance.

zdt = Temporal.ZonedDateTime.from('2020-02-01T12:30+09:00[Asia/Tokyo]');
epochSecs = zdt.epochSeconds;
  // => 1580527800
epochMs = zdt.epochMilliseconds;
  // => 1580527800000
zdt.toInstant().epochMilliseconds;
  // => 1580527800000
legacyDate = new Date(epochMs);
  // => 2020-02-01T03:30:00.000Z
  // (if the system time zone is America/Los_Angeles)
epochMicros = zdt.epochMicroseconds;
  // => 1580527800000000n
epochNanos = zdt.epochNanoseconds;
  // => 1580527800000000000n

zonedDateTime.calendar : object

The calendar read-only property gives the calendar used to calculate date/time field values. Calendar-sensitive values are used in most places, including:

Calendar-specific date/time values are NOT used in only a few places:

zonedDateTime.timeZone : Temporal.TimeZoneProtocol

The timeZone read-only property represents the persistent time zone of zonedDateTime. By storing its time zone, Temporal.ZonedDateTime is able to use that time zone when deriving other values, e.g. to automatically perform DST adjustment when adding or subtracting time.

If a non-canonical time zone ID is used, it will be normalized by Temporal into its canonical name listed in the IANA time zone database.

Usually, the time zone ID will be an IANA time zone ID. However, in unusual cases, a time zone can also be created from a time zone offset string like +05:30. Offset time zones function just like IANA time zones except that their offset can never change due to DST or political changes. This can be problematic for many use cases because by using an offset time zone you lose the ability to safely derive past or future dates because, even in time zones without DST, offsets sometimes change for political reasons (e.g. countries change their time zone). Therefore, using an IANA time zone is recommended wherever possible.

In very rare cases, you may choose to use UTC as your time zone ID. This is generally not advised because no humans actually live in the UTC time zone; it's just for computers. Also, UTC has no DST and always has a zero offset, which means that any action you'd take with Temporal.ZonedDateTime would return identical results to the same action on Temporal.PlainDateTime or Temporal.Instant. Therefore, you should almost always use Temporal.Instant to represent UTC times. When you want to convert UTC time to a real time zone, that's when Temporal.ZonedDateTime will be useful.

To change the time zone while keeping the exact time constant, use .withTimeZone(timeZone).

The time zone is a required property when creating Temporal.ZonedDateTime instances. If you don't know the time zone of your underlying data, please use Temporal.Instant and/or Temporal.PlainDateTime, neither of which have awareness of time zones.

Although this property is a Temporal.TimeZoneProtocol object (which is usually a Temporal.TimeZone except custom timezones), it will be automatically coerced to its string form (e.g. "Europe/Paris") when displayed by console.log, JSON.stringify, ${zonedDateTime.timeZone}, or other similar APIs.

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24-08:00[America/Los_Angeles]');
`Time zone is: ${zdt.timeZone}`;
  // => 'Time zone is: America/Los_Angeles'
zdt.withTimeZone('Asia/Singapore').timeZone;
  // => Asia/Singapore
zdt.withTimeZone('Asia/Chongqing').timeZone;
  // => Asia/Shanghai
  // (time zone IDs are normalized, e.g. Asia/Chongqing -> Asia/Shanghai)
zdt.withTimeZone('+05:00').timeZone;
  // => +05:00
zdt.withTimeZone('+05').timeZone;
  // => +05:00
  // (normalized to canonical form)
zdt.withTimeZone('utc').timeZone;
  // => UTC
  // (normalized to canonical form which is uppercase)
zdt.withTimeZone('GMT').timeZone;
  // => UTC
  // (normalized to canonical form)

zonedDateTime.era : string | undefined

zonedDateTime.eraYear : number | undefined

In calendars that use eras, the era and eraYear read-only properties can be used together to resolve an era-relative year. Both properties are undefined when using the ISO 8601 calendar. As inputs to from or with, era and eraYear can be used instead of year. Unlike year, eraYear may decrease as time proceeds because some eras (like the BCE era in the Gregorian calendar) count years backwards.

date = Temporal.ZonedDateTime.from('-000015-01-01T12:30[Europe/Rome][u-ca=gregory]');
date.era;
// => 'bce'
date.eraYear;
// => 16
date.year;
// => -15

zonedDateTime.dayOfWeek : number

The dayOfWeek read-only property gives the weekday number that the date falls on. For the ISO 8601 calendar, the weekday number is defined as in the ISO 8601 standard: a value between 1 and 7, inclusive, with Monday being 1, and Sunday 7. For an overview, see ISO 8601 on Wikipedia.

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24-08:00[America/Los_Angeles]');
['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'][zdt.dayOfWeek - 1]; // => 'THU'

zonedDateTime.dayOfYear : number

The dayOfYear read-only property gives the ordinal day of the year that the date falls on. For the ISO 8601 calendar, this is a value between 1 and 365, or 366 in a leap year.

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24-08:00[America/Los_Angeles]');
// ISO ordinal date
console.log(zdt.year, zdt.dayOfYear); // => '1995 341'

zonedDateTime.weekOfYear : number

The weekOfYear read-only property gives the ISO week number of the date. For the ISO 8601 calendar, this is normally a value between 1 and 52, but in a few cases it can be 53 as well. ISO week 1 is the week containing the first Thursday of the year. For more information on ISO week numbers, see for example the Wikipedia article on ISO week date.

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24-08:00[America/Los_Angeles]');
// ISO week date
console.log(zdt.year, zdt.weekOfYear, zdt.dayOfWeek); // => '1995 49 4'

zonedDateTime.daysInWeek : number

The daysInWeek read-only property gives the number of days in the week that the date falls in. For the ISO 8601 calendar, this is always 7, but in other calendar systems it may differ from week to week.

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24-08:00[America/Los_Angeles]');
zdt.daysInWeek; // => 7

zonedDateTime.daysInMonth : number

The daysInMonth read-only property gives the number of days in the month that the date falls in. For the ISO 8601 calendar, this is 28, 29, 30, or 31, depending on the month and whether the year is a leap year.

Usage example:

// Attempt to write some mnemonic poetry
const monthsByDays = {};
for (let month = 1; month <= 12; month++) {
  const zdt = Temporal.Now.zonedDateTimeISO().with({ month });
  monthsByDays[zdt.daysInMonth] = (monthsByDays[zdt.daysInMonth] || []).concat(zdt);
}

const strings = monthsByDays[30].map((zdt) => zdt.toLocaleString('en', { month: 'long' }));
// Shuffle to improve poem as determined empirically
strings.unshift(strings.pop());
const format = new Intl.ListFormat('en');
const poem = `Thirty days hath ${format.format(strings)}`;

console.log(poem);

zonedDateTime.daysInYear : number

The daysInYear read-only property gives the number of days in the year that the date falls in. For the ISO 8601 calendar, this is 365 or 366, depending on whether the year is a leap year.

Usage example:

zdt = Temporal.Now.zonedDateTimeISO();
percent = zdt.dayOfYear / zdt.daysInYear;
`The year is ${percent.toLocaleString('en', { style: 'percent' })} over!`;
// example output: "The year is 10% over!"

zonedDateTime.monthsInYear: number

The monthsInYear read-only property gives the number of months in the year that the date falls in. For the ISO 8601 calendar, this is always 12, but in other calendar systems it may differ from year to year.

Usage example:

zdt = Temporal.ZonedDateTime.from('1900-01-01T12:00+09:00[Asia/Tokyo]');
zdt.monthsInYear; // => 12

zonedDateTime.inLeapYear : boolean

The inLeapYear read-only property tells whether the year of this Temporal.ZonedDateTime is a leap year. Its value is true if the year is a leap year, and false if not.

For the ISO calendar, leap years are years evenly divisible by 4, except years evenly divisible by 100 but not evenly divisible by 400. Other calendar systems may calculate leap years differently.

Usage example:

// Is this year a leap year?
zdt = Temporal.Now.zonedDateTimeISO();
zdt.inLeapYear; // example output: true
// Is 2100 a leap year? (no, because it's divisible by 100 and not 400)
zdt.with({ year: 2100 }).inLeapYear; // => false

zonedDateTime.hoursInDay : number

The hoursInDay read-only property returns the number of real-world hours between the start of the current day (usually midnight) in zonedDateTime.timeZone to the start of the next calendar day in the same time zone. Normally days will be 24 hours long, but on days where there are DST changes or other time zone transitions, this property may return 23 or 25. In rare cases, other integers or even non-integer values may be returned, e.g. when time zone definitions change by less than one hour.

If a time zone offset transition happens exactly at midnight, the transition will impact the previous day's length.

Note that transitions that skip entire days (like the 2011 change of Pacific/Apia to the opposite side of the International Date Line) will return 24 because there are 24 real-world hours between one day's midnight and the next day's midnight.

Usage example:

Temporal.ZonedDateTime.from('2020-01-01T12:00-08:00[America/Los_Angeles]').hoursInDay;
  // => 24
  // (normal day)
Temporal.ZonedDateTime.from('2020-03-08T12:00-07:00[America/Los_Angeles]').hoursInDay;
  // => 23
  // (DST starts on this day)
Temporal.ZonedDateTime.from('2020-11-01T12:00-08:00[America/Los_Angeles]').hoursInDay;
  // => 25
  // (DST ends on this day)

zonedDateTime.startOfDay : Temporal.ZonedDateTime

The startOfDay read-only property returns a new Temporal.ZonedDateTime instance representing the earliest valid local clock time during the current calendar day and time zone of zonedDateTime.

The local time of the result is almost always 00:00, but in rare cases it could be a later time e.g. if DST starts at midnight in a time zone. For example:

const zdt = Temporal.ZonedDateTime.from('2015-10-18T12:00-02:00[America/Sao_Paulo]');
zdt.startOfDay(); // => 2015-10-18T01:00:00-02:00[America/Sao_Paulo]

Also note that some calendar systems (e.g. ethiopic) may not start days at 00:00.

Usage example:

zdt = Temporal.ZonedDateTime.from('2020-01-01T12:00-08:00[America/Los_Angeles]').startOfDay();
  // => 2020-01-01T00:00:00-08:00[America/Los_Angeles]
zdt = Temporal.ZonedDateTime.from('2018-11-04T12:00-02:00[America/Sao_Paulo]').startOfDay();
  // => 2018-11-04T01:00:00-02:00[America/Sao_Paulo]
  // Note the 1:00AM start time because the first clock hour was skipped due to DST transition
  // that started at midnight.

zonedDateTime.offsetNanoseconds : number

The offsetNanoseconds read-only property is the offset (in nanoseconds) relative to UTC of zonedDateTime.

The value of this field will change after DST transitions or after political changes to a time zone, e.g. a country switching to a new time zone.

To change the offset using with (or from using an property bag object instead of a string), use the string-typed offset field. The numeric offsetNanoseconds field is read-only and is ignored in with and from.

zdt = Temporal.ZonedDateTime.from('2020-11-01T01:30-07:00[America/Los_Angeles]');
zdt.offsetNanoseconds;
  // => -25200000000000
  // (-7 * 3600 * 1e9)

zonedDateTime.offset : string

The offset read-only property is the offset (formatted as a string) relative to UTC of the current time zone and exact instant. Examples: '-08:00' or '+05:30'

The format used is defined in the ISO 8601 standard.

The value of this field will change after DST transitions or after political changes to a time zone, e.g. a country switching to a new time zone.

This field is used to uniquely map date/time fields to an exact date/time in cases where the calendar date and clock time are ambiguous due to time zone offset transitions. Therefore, this field is accepted by from and with. The presence of this field means that zonedDateTime.toInstant() requires no parameters.

zdt = Temporal.ZonedDateTime.from('2020-11-01T01:30-07:00[America/Los_Angeles]');
zdt.offset;
  // => '-07:00'
zdt.withTimeZone('Asia/Kolkata').offset;
  // => '+05:30'

minus8Hours = '-08:00';
daylightTime0130 = Temporal.ZonedDateTime.from('2020-11-01T01:30-07:00[America/Los_Angeles]');
  // => 2020-11-01T01:30:00-07:00[America/Los_Angeles]
  // This is Pacific Daylight Time 1:30AM
repeated0130 = daylightTime0130.with({ offset: minus8Hours });
  // => 2020-11-01T01:30:00-08:00[America/Los_Angeles]
  // This is Pacific Standard Time 1:30AM

Methods

zonedDateTime.with(zonedDateTimeLike: object | string, options?: object) : Temporal.ZonedDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object.

This method creates a new Temporal.ZonedDateTime which is a copy of zonedDateTime, but any properties present on zonedDateTimeLike override the ones already present on zonedDateTime.

Since Temporal.ZonedDateTime objects each represent a fixed date and time, this method will create a new instance instead of modifying the existing instance.

If the result is earlier or later than the range of dates that Temporal.ZonedDateTime can represent (approximately half a million years centered on the Unix epoch), then this method will throw a RangeError regardless of overflow.

NOTE: The allowed values for the zonedDateTimeLike.month property start at 1, which is different from legacy Date where months are represented by zero-based indices (0 to 11).

If a timeZone or calendar property is included, this function will throw an exception. To convert to a new time zone while updating the clock time, use the withTimeZone() method, and to keep clock time as-is while resetting the time zone, use the .toPlainDateTime() method instead. Examples:

// update local time to match new time zone
const sameInstantInOtherTz = zdt.withTimeZone('Europe/London');
// create instance with same local time in a new time zone
const newTzSameLocalTime = zdt.toPlainDateTime().toZonedDateTime('Europe/London');

Some input values can cause conflict between zonedDateTime's time zone and its UTC offset. This can happen when offset is included in the input, and can also happen when setting date/time values on the opposite side of a time zone offset transition like DST starting or ending. The offset option can resolve this conflict.

Unlike the from() method where offset defaults to 'reject', the offset option in with defaults to 'prefer'. This default prevents DST disambiguation from causing unexpected one-hour changes in exact time after making small changes to clock time fields. For example, if a Temporal.ZonedDateTime is set to the "second" 1:30AM on a day where the 1-2AM clock hour is repeated after a backwards DST transition, then calling .with({minute: 45}) will result in an ambiguity which is resolved using the default offset: 'prefer' option. Because the existing offset is valid for the new time, it will be retained so the result will be the "second" 1:45AM. However, if the existing offset is not valid for the new result (e.g. .with({hour: 0})), then the default behavior will change the offset to match the new local time in that time zone.

Options on with behave identically to options on from, with only the following exceptions:

Please see the documentation of from for more details on options behavior.

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:00-06:00[America/Chicago]');
zdt.with({ year: 2015, minute: 31 }); // => 2015-12-07T03:31:00-06:00[America/Chicago]

zonedDateTime.withPlainTime(plainTime?: object | string) : Temporal.PlainDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object which replaces the clock time of zonedDateTime with the clock time represented by plainTime.

Valid input to withPlainTime is the same as valid input to Temporal.PlainTime.from, including strings like 12:15:36, plain object property bags like { hour: 20, minute: 30 }, or Temporal objects that contain time fields: Temporal.PlainTime, Temporal.ZonedDateTime, or Temporal.PlainDateTime.

This method is similar to with, but with a few important differences:

If plainTime is a Temporal.PlainTime object, then this method returns the same result as plainTime.toZonedDateTime({ plainTime: zonedDateTime, timeZone: zonedDateTime}) but can be easier to use, especially when chained to previous operations that return a Temporal.ZonedDateTime.

Usage example:

zdt = Temporal.ZonedDateTime.from('2015-12-07T03:24:30.000003500-08:00[America/Los_Angeles]');
zdt.withPlainTime({ hour: 10 }); // => 2015-12-07T10:00:00-08:00[America/Los_Angeles]
time = Temporal.PlainTime.from('11:22');
zdt.withPlainTime(time); // => 2015-12-07T11:22:00-08:00[America/Los_Angeles]
zdt.withPlainTime('12:34'); // => 2015-12-07T12:34:00-08:00[America/Los_Angeles]

// easier for chaining
zdt.add({ days: 2, hours: 22 }).withPlainTime('00:00'); // => 2015-12-10T00:00:00-08:00[America/Los_Angeles]

zonedDateTime.withPlainDate(plainDate: object | string) : Temporal.ZonedDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object which replaces the calendar date of zonedDateTime with the calendar date represented by plainDate.

Valid input to withPlainDate is the same as valid input to Temporal.PlainDate.from, including strings like 2000-03-01, plain object property bags like { year: 2020, month: 3, day: 1 }, or Temporal objects that contain a year, month, and day property, including Temporal.PlainDate, Temporal.ZonedDateTime, or Temporal.PlainDateTime.

All three date units (year, month, and day) are required. Temporal.YearMonth and Temporal.MonthDay are not valid input because they lack all date units. Both of those types have a toPlainDate method that can be used to obtain a Temporal.PlainDate which can in turn be used as input to withPlainDate.

If plainDate contains a non-ISO 8601 calendar, then the result of withPlainDate will be the calendar of plainDate. However, if zonedDateTime.calendar is already a non-ISO 8601 calendar, then this method wil throw a RangeError. To resolve the error, first convert one of the instances to the same calendar or the ISO 8601 calendar, e.g. using .withCalendar('iso8601').

This method is similar to with, but with a few important differences:

If plainDate is a Temporal.PlainDate object, then this method returns the same result as plainDate.toZonedDateTime({ plainDate: zonedDateTime, timeZone: zonedDateTime}) but can be easier to use, especially when chained to previous operations that return a Temporal.ZonedDateTime.

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30-08:00[America/Los_Angeles]');
zdt.withPlainDate({ year: 2000, month: 6, day: 1 }); // => 2000-06-01T03:24:30-07:00[America/Los_Angeles]
date = Temporal.PlainDate.from('2020-01-23');
zdt.withPlainDate(date); // => 2020-01-23T03:24:30-08:00[America/Los_Angeles]
zdt.withPlainDate('2018-09-15'); // => 2018-09-15T03:24:30-07:00[America/Los_Angeles]

// easier for chaining
zdt.add({ hours: 12 }).withPlainDate('2000-06-01'); // => 2000-06-01T15:24:30-07:00[America/Los_Angeles]

// result contains a non-ISO calendar if present in the input
zdt.withCalendar('japanese').withPlainDate('2008-09-06'); // => 2008-09-06T03:24:30-07:00[America/Los_Angeles][u-ca=japanese]
zdt.withPlainDate('2017-09-06[u-ca=japanese]'); // => 2017-09-06T03:24:30-07:00[America/Los_Angeles][u-ca=japanese]
/* WRONG */ zdt.withCalendar('japanese').withPlainDate('2017-09-06[u-ca=hebrew]'); // => RangeError (calendar conflict)

zonedDateTime.withTimeZone(timeZone: object | string) : Temporal.ZonedDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object which is the date indicated by zonedDateTime, projected into timeZone.

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30+09:00[Asia/Tokyo]');
zdt.toString(); // => '1995-12-07T03:24:30+09:00[Asia/Tokyo]'
zdt.withTimeZone('Africa/Accra').toString(); // => '1995-12-06T18:24:30+00:00[Africa/Accra]'

zonedDateTime.withCalendar(calendar: object | string) : Temporal.ZonedDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object which is the date indicated by zonedDateTime, projected into calendar.

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30.000003500+09:00[Asia/Tokyo][u-ca=japanese]');
`${zdt.era} ${zdt.eraYear}`; // => 'heisei 7'
zdt.withCalendar('gregory').eraYear; // => 1995

zonedDateTime.add(duration: object, options?: object) : Temporal.ZonedDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object representing the sum of zonedDateTime plus duration.

This method adds duration to zonedDateTime.

The duration argument is an object with properties denoting a duration, such as { hours: 5, minutes: 30 }, or a Temporal.Duration object. Adding a negative duration like { hours: -5, minutes: -30 } is equivalent to subtracting the absolute value of that duration.

Addition and subtraction are performed according to rules defined in RFC 5545 (iCalendar):

These rules make arithmetic with Temporal.ZonedDateTime "DST-safe", which means that the results most closely match the expectations of both real-world users and implementers of other standards-compliant calendar applications. These expectations include:

Some arithmetic operations may be ambiguous, e.g. because months have different lengths. For example, adding one month to August 31 would result in September 31, which doesn't exist. For these cases, the overflow option tells what to do:

Additionally, if the result is earlier or later than the range of dates that Temporal.ZonedDateTime can represent (approximately half a million years centered on the Unix epoch), then this method will throw a RangeError regardless of overflow.

Usage example:

zdt = Temporal.ZonedDateTime.from('2020-03-08T00:00-08:00[America/Los_Angeles]');
// Add a day to get midnight on the day after DST starts
laterDay = zdt.add({ days: 1 });
  // => 2020-03-09T00:00:00-07:00[America/Los_Angeles]
  // Note that the new offset is different, indicating the result is adjusted for DST.
laterDay.since(zdt, { largestUnit: 'hour' }).hours;
  // => 23
  // because one clock hour lost to DST

laterHours = zdt.add({ hours: 24 });
  // => 2020-03-09T01:00:00-07:00[America/Los_Angeles]
  // Adding time units doesn't adjust for DST. Result is 1:00AM: 24 real-world
  // hours later because a clock hour was skipped by DST.
laterHours.since(zdt, { largestUnit: 'hour' }).hours; // => 24

zonedDateTime.subtract(duration: object, options?: object) : Temporal.ZonedDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object representing the result of zonedDateTime minus duration.

This method subtracts a duration from zonedDateTime.

The duration argument is an object with properties denoting a duration, such as { hours: 5, minutes: 30 }, or a Temporal.Duration object. Subtracting a negative duration like { hours: -5, minutes: -30 } is equivalent to adding the absolute value of that duration.

Addition and subtraction are performed according to rules defined in RFC 5545 (iCalendar):

These rules make arithmetic with Temporal.ZonedDateTime "DST-safe", which means that the results most closely match the expectations of both real-world users and implementers of other standards-compliant calendar applications. These expectations include:

Some arithmetic operations may be ambiguous, e.g. because months have different lengths. For example, subtracting one month from October 31 would result in September 31, which doesn't exist. For these cases, the overflow option tells what to do:

Additionally, if the result is earlier or later than the range of dates that Temporal.ZonedDateTime can represent (approximately half a million years centered on the Unix epoch), then this method will throw a RangeError regardless of overflow.

Usage example:

zdt = Temporal.ZonedDateTime.from('2020-03-09T00:00-07:00[America/Los_Angeles]');
// Add a day to get midnight on the day after DST starts
earlierDay = zdt.subtract({ days: 1 });
  // => 2020-03-08T00:00:00-08:00[America/Los_Angeles]
  // Note that the new offset is different, indicating the result is adjusted for DST.
earlierDay.since(zdt, { largestUnit: 'hour' }).hours;
  // => -23
  // because one clock hour lost to DST

earlierHours = zdt.subtract({ hours: 24 });
  // => 2020-03-07T23:00:00-08:00[America/Los_Angeles]
  // Subtracting time units doesn't adjust for DST. Result is 11:00PM: 24 real-world
  // hours earlier because a clock hour was skipped by DST.
earlierHours.since(zdt, { largestUnit: 'hour' }).hours; // => -24

zonedDateTime.until(other: Temporal.ZonedDateTime, options?: object) : Temporal.Duration

Parameters:

Returns: a Temporal.Duration representing the elapsed time after zonedDateTime and until other.

This method computes the difference between the two times represented by zonedDateTime and other, optionally rounds it, and returns it as a Temporal.Duration object. If other is earlier than zonedDateTime then the resulting duration will be negative. The returned Temporal.Duration, when added to zonedDateTime with the same options, will yield other.

The largestUnit option controls how the resulting duration is expressed. The returned Temporal.Duration object will not have any nonzero fields that are larger than the unit in largestUnit. For example, a difference of two hours will become 7200 seconds when largestUnit is "seconds". However, a difference of 30 seconds will still be 30 seconds if largestUnit is "hours". A value of 'auto' means 'hour', unless smallestUnit is 'year', 'month', 'week', or 'day', in which case largestUnit is equal to smallestUnit.

You can round the result using the smallestUnit, roundingIncrement, and roundingMode options. These behave as in the Temporal.Duration.round() method, but increments of days and larger are allowed. Because rounding to an increment expressed in days or larger units requires a reference point, zonedDateTime is used as the starting point in that case. The default is to do no rounding.

The duration returned is a "hybrid" duration. This means that the duration's date portion represents full calendar days like Temporal.PlainDateTime.prototype.until() would return, while its time portion represents real-world elapsed time like Temporal.Instant.prototype.until() would return. This "hybrid duration" approach automatically adjusts for DST and matches widely-adopted industry standards like RFC 5545 (iCalendar). It also matches the behavior of popular JavaScript libraries like moment.js and date-fns.

Examples:

If largestUnit is 'hour' or smaller, then the result will be the same as if Temporal.Instant.prototype.until() was used. If both values have the same local time, then the result will be the same as if Temporal.PlainDateTime.prototype.until() was used. To calculate the difference between calendar dates only, use .toPlainDate().until(other.toPlainDate()). To calculate the difference between clock times only, use .toPlainTime().until(other.toPlainTime()).

If the other Temporal.ZonedDateTime is in a different time zone, then the same days can be different lengths in each time zone, e.g. if only one of them observes DST. Therefore, a RangeError will be thrown if largestUnit is 'day' or larger and the two instances' time zones have different id fields. To work around this limitation, transform one of the instances to the other's time zone using .withTimeZone(other.timeZone) and then calculate the same-timezone difference. Because of the complexity and ambiguity involved in cross-timezone calculations involving days or larger units, 'hour' is the default for largestUnit.

Take care when using milliseconds, microseconds, or nanoseconds as the largest unit. For some durations, the resulting value may overflow Number.MAX_SAFE_INTEGER and lose precision in its least significant digit(s). Nanoseconds values will overflow and lose precision after about 104 days. Microseconds can fit about 285 years without losing precision, and milliseconds can handle about 285,000 years without losing precision.

Computing the difference between two dates in different calendar systems is not supported. If you need to do this, choose the calendar in which the computation takes place by converting one of the dates with zonedDateTime.withCalendar.

Usage example:

zdt1 = Temporal.ZonedDateTime.from('1995-12-07T03:24:30.000003500+05:30[Asia/Kolkata]');
zdt2 = Temporal.ZonedDateTime.from('2019-01-31T15:30+05:30[Asia/Kolkata]');
zdt1.until(zdt2);
  // => PT202956H5M29.9999965S
zdt1.until(zdt2, { largestUnit: 'year' });
  // => P23Y1M24DT12H5M29.9999965S
zdt2.until(zdt1, { largestUnit: 'year' });
  // => -P23Y1M24DT12H5M29.9999965S
zdt1.until(zdt2, { largestUnit: 'nanosecond' });
  // => PT730641929.999996544S
  // (precision lost)

// Rounding, for example if you don't care about sub-seconds
zdt1.until(zdt2, { smallestUnit: 'second' });
  // => PT202956H5M29S

// Months and years can be different lengths
[jan1, feb1, mar1] = [1, 2, 3].map((month) =>
  Temporal.ZonedDateTime.from({ year: 2020, month, day: 1, timeZone: 'Asia/Seoul' })
);
jan1.until(feb1, { largestUnit: 'day' }); // => P31D
jan1.until(feb1, { largestUnit: 'month' }); // => P1M
feb1.until(mar1, { largestUnit: 'day' }); // => P29D
feb1.until(mar1, { largestUnit: 'month' }); // => P1M
jan1.until(mar1, { largestUnit: 'day' }); // => P60D

zonedDateTime.since(other: Temporal.ZonedDateTime, options?: object) : Temporal.Duration

Parameters:

Returns: a Temporal.Duration representing the elapsed time before zonedDateTime and since other.

This method computes the difference between the two times represented by zonedDateTime and other, optionally rounds it, and returns it as a Temporal.Duration object. If other is later than zonedDateTime then the resulting duration will be negative.

This method is similar to Temporal.ZonedDateTime.prototype.until(), but reversed. The returned Temporal.Duration, when subtracted from zonedDateTime using the same options, will yield other. Using default options, zdt1.since(zdt2) yields the same result as zdt1.until(zdt2).negated(), but results may differ with options like { largestUnit: 'day' }.

Usage example:

zdt1 = Temporal.ZonedDateTime.from('1995-12-07T03:24:30.000003500+05:30[Asia/Kolkata]');
zdt2 = Temporal.ZonedDateTime.from('2019-01-31T15:30+05:30[Asia/Kolkata]');
zdt2.since(zdt1); // => PT202956H5M29.9999965S

zonedDateTime.round(options: object) : Temporal.ZonedDateTime

Parameters:

Returns: a new Temporal.ZonedDateTime object which is zonedDateTime rounded to roundingIncrement of smallestUnit.

Rounds zonedDateTime to the given unit and increment, and returns the result as a new Temporal.ZonedDateTime object.

The smallestUnit option determines the unit to round to. For example, to round to the nearest minute, use smallestUnit: 'minute'. This option is required.

The roundingIncrement option allows rounding to an integer number of units. For example, to round to increments of a half hour, use { smallestUnit: 'minute', roundingIncrement: 30 }.

The value given as roundingIncrement must divide evenly into the next highest unit after smallestUnit, and must not be equal to it. (For example, if smallestUnit is 'minute', then the number of minutes given by roundingIncrement must divide evenly into 60 minutes, which is one hour. The valid values in this case are 1 (default), 2, 3, 4, 5, 6, 10, 12, 15, 20, and 30. Instead of 60 minutes, use 1 hour.)

If smallestUnit is 'day', then 1 is the only allowed value for roundingIncrement.

The roundingMode option controls how the rounding is performed.

Example usage:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30.000003500-08:00[America/Los_Angeles]');

// Round to a particular unit
zdt.round({ smallestUnit: 'hour' });
  // => 1995-12-07T03:00:00-08:00[America/Los_Angeles]
// Round to an increment of a unit, e.g. half an hour:
zdt.round({ roundingIncrement: 30, smallestUnit: 'minute' });
  // => 1995-12-07T03:30:00-08:00[America/Los_Angeles]
// Round to the same increment but round down instead:
zdt.round({ roundingIncrement: 30, smallestUnit: 'minute', roundingMode: 'floor' });
  // => 1995-12-07T03:00:00-08:00[America/Los_Angeles]

zonedDateTime.equals(other: Temporal.ZonedDateTime) : boolean

Parameters:

Returns: true if zonedDateTime and other are have equivalent fields (date/time fields, offset, time zone ID, and calendar ID), or false if not.

Compares two Temporal.ZonedDateTime objects for equality.

This function exists because it's not possible to compare using zonedDateTime == other or zonedDateTime === other, due to ambiguity in the primitive representation and between Temporal types.

If you don't need to know the order in which two events occur, then this function is easier to use than Temporal.ZonedDateTime.compare. But both methods do the same thing, so a 0 returned from compare implies a true result from equals, and vice-versa.

Note that two Temporal.ZonedDateTime instances can have the same clock time, time zone, and calendar but still be unequal, e.g. when a clock hour is repeated after DST ends in the Fall. In this case, the two instances will have different offsetNanoseconds field values.

To ignore calendars, convert both instances to use the ISO 8601 calendar:

zdt.withCalendar('iso8601').equals(other.withCalendar('iso8601'));

To ignore both time zones and calendars, compare the instants of both:

zdt.toInstant().equals(other.toInstant());

Example usage:

zdt1 = Temporal.ZonedDateTime.from('1995-12-07T03:24:30.000003500+01:00[Europe/Paris]');
zdt2 = Temporal.ZonedDateTime.from('1995-12-07T03:24:30.000003500+01:00[Europe/Brussels]');
zdt1.equals(zdt2); // => false (same offset but different time zones)
zdt1.equals(zdt1); // => true

zonedDateTime.toString(options?: object) : string

Parameters:

Returns: a string containing an ISO 8601 date+time+offset format, a bracketed time zone suffix, and (if the calendar is not iso8601) a calendar suffix.

Examples:

This method overrides the Object.prototype.toString() method and provides a convenient, unambiguous string representation of zonedDateTime. The string is "round-trippable". This means that it can be passed to Temporal.ZonedDateTime.from() to create a new Temporal.ZonedDateTime object with the same field values as the original.

The output precision can be controlled with the fractionalSecondDigits or smallestUnit option. If no options are given, the default is fractionalSecondDigits: 'auto', which omits trailing zeroes after the decimal point.

The value is truncated to fit the requested precision, unless a different rounding mode is given with the roundingMode option, as in Temporal.PlainDateTime.round(). Note that rounding may change the value of other units as well.

Normally, a calendar annotation is shown when zonedDateTime's calendar is not the ISO 8601 calendar. By setting the calendarName option to 'always' or 'never' this can be overridden to always or never show the annotation, respectively. For more information on the calendar annotation, see ISO string extensions.

Likewise, passing 'never' to the timeZoneName or offset options controls whether the time zone offset (+01:00) or name annotation ([Europe/Paris]) are shown.

The string format output by this method can be parsed by java.time.ZonedDateTime as long as the calendar annotation is not output. For more information on Temporal's extensions to the ISO string format and the progress towards becoming a published standard, see ISO standard extensions.

Example usage:

zdt = Temporal.ZonedDateTime.from({ year: 2019, month: 12, day: 1, hour: 12, timeZone: 'Africa/Lagos' });
zdt.toString(); // => '2019-12-01T12:00:00+01:00[Africa/Lagos]'
zdt = zdt.withCalendar('japanese');
zdt.toString(); // => '2019-12-01T12:00:00+01:00[Africa/Lagos][u-ca=japanese]'

zonedDateTime.toLocaleString(locales?: string | array<string>, options?: object) : string

Parameters:

Returns: a language-sensitive representation of zonedDateTime.

This method overrides Object.prototype.toLocaleString() to provide a human-readable, language-sensitive representation of zonedDateTime.

The locales and options arguments are the same as in the constructor to Intl.DateTimeFormat.

options.timeZone will be automatically set from the time zone of of zonedDateTime. If a different time zone ID is provided in options.timeZone, a RangeError will be thrown. To display a Temporal.ZonedDateTime value in a different time zone, use withTimeZone(timeZone).toLocaleString().

Example usage:

zdt = Temporal.ZonedDateTime.from('2019-12-01T12:00+01:00[Europe/Berlin]');
zdt.toLocaleString(); // example output: 12/1/2019, 12:00:00 PM
zdt.toLocaleString('de-DE'); // => '1.12.2019, 12:00:00 MEZ'
options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
zdt.toLocaleString('de-DE', options); // => 'Sonntag, 1. Dezember 2019'
/* WRONG */ zdt.toLocaleString('de-DE', { timeZone: 'Pacific/Auckland' });
  // => RangeError: Time zone option Pacific/Auckland does not match actual time zone Europe/Berlin
zdt.withTimeZone('Pacific/Auckland').toLocaleString('de-DE'); // => '2.12.2019, 0:00:00 GMT+13'
zdt.toLocaleString('en-US-u-nu-fullwide-hc-h12'); // => '12/1/2019, 12:00:00 PM GMT+1'

zonedDateTime.toJSON() : string

Returns: a string in the ISO 8601 date format representing zonedDateTime.

This method is the same as zonedDateTime.toString(). It is usually not called directly, but it can be called automatically by JSON.stringify().

The reverse operation, recovering a Temporal.ZonedDateTime object from a string, is Temporal.ZonedDateTime.from(), but it cannot be called automatically by JSON.parse(). If you need to rebuild a Temporal.ZonedDateTime object from a JSON string, then you need to know the names of the keys that should be interpreted as Temporal.ZonedDateTimes. In that case you can build a custom "reviver" function for your use case.

Example usage:

const event = {
  id: 311,
  name: 'FictionalConf 2018',
  openingZonedDateTime: Temporal.ZonedDateTime.from('2018-07-06T10:00+05:30[Asia/Kolkata]'),
  closingZonedDateTime: Temporal.ZonedDateTime.from('2018-07-08T18:15+05:30[Asia/Kolkata]')
};
const str = JSON.stringify(event, null, 2);
console.log(str);
// =>
// {
//   "id": 311,
//   "name": "FictionalConf 2018",
//   "openingZonedDateTime": "2018-07-06T10:00+05:30[Asia/Calcutta]",
//   "closingZonedDateTime": "2018-07-08T18:15+05:30[Asia/Calcutta]"
// }

// To rebuild from the string:
function reviver(key, value) {
  if (key.endsWith('ZonedDateTime')) return Temporal.ZonedDateTime.from(value);
  return value;
}
JSON.parse(str, reviver);

zonedDateTime.valueOf()

This method overrides Object.prototype.valueOf() and always throws an exception. This is because it's not possible to compare Temporal.ZonedDateTime objects with the relational operators <, <=, >, or >=. Use Temporal.ZonedDateTime.compare() for this, or zonedDateTime.equals() for equality.

zonedDateTime.toInstant() : Temporal.Instant

Returns: A Temporal.Instant object that represents the same instant as zonedDateTime.

zonedDateTime.toPlainDate() : Temporal.PlainDate

Returns: a Temporal.PlainDate object that is the same as the date portion of zonedDateTime.

zonedDateTime.toPlainTime() : Temporal.PlainTime

Returns: a Temporal.PlainTime object that is the same as the wall-clock time portion of zonedDateTime.

zonedDateTime.toPlainDateTime() : Temporal.PlainDateTime

Returns: a Temporal.PlainDateTime object that is the same as the date and time portion of zonedDateTime.

NOTE: After a Temporal.ZonedDateTime is converted to Temporal.PlainDateTime, it will no longer be aware of its time zone. This means that subsequent operations like arithmetic or with will not adjust for DST and may not yield the same results as equivalent operations with Temporal.ZonedDateTime. However, unless you perform those operations across a time zone offset transition, it's impossible to notice the difference. Therefore, be very careful when performing this conversion because subsequent results may look correct most of the time while failing around time zone transitions like when DST starts or ends.

zonedDateTime.toPlainYearMonth() : Temporal.PlainYearMonth

Returns: a Temporal.PlainYearMonth object that is the same as the year and month of zonedDateTime.

zonedDateTime.toPlainMonthDay() : Temporal.PlainMonthDay

Returns: a Temporal.PlainMonthDay object that is the same as the month and day of zonedDateTime.

The above six methods can be used to convert Temporal.ZonedDateTime into a Temporal.Instant, Temporal.PlainDate, Temporal.PlainTime, Temporal.PlainDateTime, Temporal.PlainYearMonth, or Temporal.PlainMonthDay respectively. The converted object carries a copy of all the relevant data of zonedDateTime (for example, in toPlainDate(), the year, month, and day properties are the same.)

Usage example:

zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30+02:00[Africa/Johannesburg]');
zdt.toInstant(); // => 1995-12-07T01:24:30Z
zdt.toPlainDateTime(); // => 1995-12-07T03:24:30
zdt.toPlainDate(); // => 1995-12-07
zdt.toPlainYearMonth(); // => 1995-12
zdt.toPlainMonthDay(); // => 12-07
zdt.toPlainTime(); // => 03:24:30

zonedDateTime.getISOFields(): { isoYear: number, isoMonth: number, isoDay: number, hour: number, minute: number, second: number, millisecond: number, microsecond: number, nanosecond: number, offset: string, timeZone: object, calendar: object }

Returns: a plain object with properties expressing zonedDateTime in the ISO 8601 calendar, including all date/time fields as well as the calendar, timeZone, and offset properties.

This is an advanced method that's mainly useful if you are implementing a custom calendar. Most developers will not need to use it.

Usage example:

// get a Temporal.ZonedDateTime in `hebrew` calendar system
zdt = Temporal.ZonedDateTime.from('2019-02-23T03:24:30.000003500[Europe/Rome]').withCalendar('hebrew');

// Month in Hebrew calendar is month 6 of leap year 5779
zdt.month; // => 6
zdt.getISOFields().isoMonth; // => 2

// Instead of calling getISOFields, the pattern below is recommended for most use cases
zdt.withCalendar('iso8601').month; // => 2