ZonedDateTime
A ZonedDateTime represents a date and time in a specific time zone and calendar system.
install | yarn add @internationalized/date |
---|---|
version | 3.0.0-rc.0 |
usage | import {ZonedDateTime} from '@internationalized/date' |
Introduction#
A ZonedDateTime
object represents an exact date and time in a specific time zone, in a specific calendar system such as the Gregorian calendar. Use this type to represent an exact moment in time at a particular location on Earth.
A ZonedDateTime
can be created using the constructor. This example creates a date that represents February 3rd, 2022 at 9:15 AM in the Gregorian calendar system, with a time zone of "America/Los Angeles"
.
import {ZonedDateTime} from '@internationalized/date';
let date = new ZonedDateTime(
// Date
2022, 2, 3,
// Time zone and UTC offset
'America/Los_Angeles', -28800000,
// Time
12, 24, 45
);
import {ZonedDateTime} from '@internationalized/date';
let date = new ZonedDateTime(
// Date
2022, 2, 3,
// Time zone and UTC offset
'America/Los_Angeles', -28800000,
// Time
12, 24, 45
);
import {ZonedDateTime} from '@internationalized/date';
let date =
new ZonedDateTime(
// Date
2022,
2,
3,
// Time zone and UTC offset
'America/Los_Angeles',
-28800000,
// Time
12,
24,
45
);
You can also create a ZonedDateTime
by parsing an ISO 8601 formatted string using the one of the following functions:
parseZonedDateTime
– This function parses a date with an explicit time zone and optional UTC offset attached (e.g."2021-11-07T00:45[America/Los_Angeles]"
or"2021-11-07T00:45-07:00[America/Los_Angeles]"
). This format preserves the maximum amount of information. If the exact local time and time zone that a user selected is important, use this format. Storing the time zone and offset that was selected rather than converting to UTC ensures that the local time is correct regardless of daylight saving rule changes (e.g. if a locale abolishes DST). Examples where this applies include calendar events, reminders, and other times that occur in a particular location.parseAbsolute
– This function parses an absolute date and time that occurs at the same instant at all locations on Earth. It can be represented in UTC (e.g."2021-11-07T07:45:00Z"
), or stored with a particular offset (e.g."2021-11-07T07:45:00-07:00"
). A time zone identifier, e.g.America/Los_Angeles
, must be passed, and the result will be converted into that time zone. Absolute times are the best way to represent events that occurred in the past, or future events where an exact time is needed, regardless of time zone.parseAbsoluteToLocal
– This function parses an absolute date and time into the current user's local time zone. It is a shortcut forparseAbsolute
, and accepts the same formats.
import {parseZonedDateTime} from '@internationalized/date';
let date = parseZonedDateTime('2022-11-07T00:45[America/Los_Angeles]');
let date = parseAbsolute('2021-11-07T07:45:00Z', 'America/Los_Angeles');
let date = parseAbsoluteToLocal('2021-11-07T07:45:00Z');
import {parseZonedDateTime} from '@internationalized/date';
let date = parseZonedDateTime(
'2022-11-07T00:45[America/Los_Angeles]'
);
let date = parseAbsolute(
'2021-11-07T07:45:00Z',
'America/Los_Angeles'
);
let date = parseAbsoluteToLocal('2021-11-07T07:45:00Z');
import {parseZonedDateTime} from '@internationalized/date';
let date =
parseZonedDateTime(
'2022-11-07T00:45[America/Los_Angeles]'
);
let date = parseAbsolute(
'2021-11-07T07:45:00Z',
'America/Los_Angeles'
);
let date =
parseAbsoluteToLocal(
'2021-11-07T07:45:00Z'
);
Once you have a ZonedDateTime
object, you can read its properties, or manipulate it as described in the Manipulating dates section below. You can also convert it to an ISO 8601 string, native JavaScript Date
object, or another representation. See the Conversion section below for details.
let date = new ZonedDateTime(
2022, 2, 3,
'America/Los_Angeles', -28800000,
12, 24, 45
);
date.toString(); // '2022-02-03T12:24:45-08:00[America/Los_Angeles]'
let date = new ZonedDateTime(
2022,
2,
3,
'America/Los_Angeles',
-28800000,
12,
24,
45
);
date.toString(); // '2022-02-03T12:24:45-08:00[America/Los_Angeles]'
let date =
new ZonedDateTime(
2022,
2,
3,
'America/Los_Angeles',
-28800000,
12,
24,
45
);
date.toString(); // '2022-02-03T12:24:45-08:00[America/Los_Angeles]'
Interface#
Properties
Name | Type | Description |
calendar | Calendar | The calendar system associated with this date, e.g. Gregorian. |
era | string | The calendar era for this date, e.g. "BC" or "AD". |
year | number | The year of this date within the era. |
month | number | The month number within the year. Note that some calendar systems such as Hebrew may have a variable number of months per year. Therefore, month numbers may not always correspond to the same month names in different years. |
day | number | The day number within the month. |
hour | number | The hour in the day, numbered from 0 to 23. |
minute | number | The minute in the hour. |
second | number | The second in the minute. |
millisecond | number | The millisecond in the second. |
timeZone | string | The IANA time zone identifier that this date and time is represented in. |
offset | number | The UTC offset for this time, in seconds. |
Methods
Method | Description |
constructor(
(...args: any[]
)): void | |
copy(): ZonedDateTime | Returns a copy of this date. |
add(
(duration: DateTimeDuration
)): void | Returns a new ZonedDateTime with the given duration added to it. |
subtract(
(duration: DateTimeDuration
)): void | Returns a new ZonedDateTime with the given duration subtracted from it. |
set(
(fields: DateFields
& & TimeFields,
, disambiguation?: Disambiguation
)): void | Returns a new ZonedDateTime with the given fields set to the provided values. Other fields will be constrained accordingly. |
cycle(
field: DateField
| | TimeField,
amount: number,
options?: CycleTimeOptions
): void | Returns a new |
toDate(): void | Converts the date to a native JavaScript Date object. |
toString(): void | Converts the date to an ISO 8601 formatted string, including the UTC offset and time zone identifier. |
toAbsoluteString(): void | Converts the date to an ISO 8601 formatted string in UTC. |
compare(
(b: CalendarDate
| CalendarDateTime
| ZonedDateTime
)): void | Compares this date with another. A negative result indicates that this date is before the given one, and a positive date indicates that it is after. |
Calendar systems#
By default, ZonedDateTime
uses the Gregorian calendar system, but many other calendar systems that are used around the world are supported, such as Hebrew, Indian, Islamic, Buddhist, Ethiopic, and more. A Calendar
instance can be passed to the ZonedDateTime
constructor to represent dates in that calendar system.
This example creates a date in the Buddhist calendar system, which is equivalent to April 4th, 2020 at 9:15 AM in the Gregorian calendar.
import {BuddhistCalendar} from '@internationalized/date';
let date = new ZonedDateTime(
new BuddhistCalendar(), 2563, 4, 30,
'America/Los_Angeles', -28800000,
9, 15
);
import {BuddhistCalendar} from '@internationalized/date';
let date = new ZonedDateTime(
new BuddhistCalendar(), 2563, 4, 30,
'America/Los_Angeles', -28800000,
9, 15
);
import {BuddhistCalendar} from '@internationalized/date';
let date =
new ZonedDateTime(
new BuddhistCalendar(),
2563,
4,
30,
'America/Los_Angeles',
-28800000,
9,
15
);
See the Calendar docs for details about the supported calendars.
Eras#
Many calendar systems have only one era, or a modern era and a pre-modern era (e.g. AD and BC in the Gregorian calendar). However, other calendar systems may have many eras. For example, the Japanese calendar has eras for the reign of each Emperor. ZonedDateTime
represents eras using string identifiers, which can be passed as an additional parameter to the constructor before the year. When eras are present, years are numbered starting from 1 within the era.
This example creates a date in the Japanese calendar system, which is equivalent to April 4th, 2020 at 9:15 AM in the Gregorian calendar.
import {JapaneseCalendar} from '@internationalized/date';
let date = new ZonedDateTime(
new JapaneseCalendar(), 'heisei', 31, 4, 30,
'America/Los_Angeles', -28800000,
9, 15
);
import {JapaneseCalendar} from '@internationalized/date';
let date = new ZonedDateTime(
new JapaneseCalendar(), 'heisei', 31, 4, 30,
'America/Los_Angeles', -28800000,
9, 15
);
import {JapaneseCalendar} from '@internationalized/date';
let date =
new ZonedDateTime(
new JapaneseCalendar(),
'heisei',
31,
4,
30,
'America/Los_Angeles',
-28800000,
9,
15
);
A list of valid era identifiers can be retrieved using the getEras
method of a Calendar
instance. If an era is not provided, the date is assumed to be in the current era.
Converting between calendars#
The toCalendar
function can be used to convert a date from one calendar system to another.
This example converts a Gregorian date to a Hebrew one.
import {toCalendar, HebrewCalendar} from '@internationalized/date';
let gregorianDate = new ZonedDateTime(
2020, 9, 19,
'America/Los_Angeles', -28800000,
10, 30
);
let hebrewDate = toCalendar(gregorianDate, new HebrewCalendar());
import {
HebrewCalendar,
toCalendar
} from '@internationalized/date';
let gregorianDate = new ZonedDateTime(
2020,
9,
19,
'America/Los_Angeles',
-28800000,
10,
30
);
let hebrewDate = toCalendar(
gregorianDate,
new HebrewCalendar()
);
import {
HebrewCalendar,
toCalendar
} from '@internationalized/date';
let gregorianDate =
new ZonedDateTime(
2020,
9,
19,
'America/Los_Angeles',
-28800000,
10,
30
);
let hebrewDate =
toCalendar(
gregorianDate,
new HebrewCalendar()
);
Manipulating dates#
Adding and subtracting durations#
A DateTimeDuration
is an object that represents an amount of time, with fields such as years
, months
, hours
, and minutes
. The add
and subtract
methods of ZonedDateTime
objects can be used to adjust the date by the given duration. These methods return a new date, and do not mutate the original.
let date = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
date.add({ weeks: 1 }); // 2022-02-10T09:45[America/Los_Angeles]
date.add({ months: 1 }); // 2022-03-03T09:45[America/Los_Angeles]
date.add({ years: 1, months: 1, days: 1 }); // 2023-03-04T09:45[America/Los_Angeles]
date.add({ hours: 1 }); // 2022-02-03T10:45[America/Los_Angeles]
date.add({ minutes: 30 }); // 2022-02-03T10:15[America/Los_Angeles]
date.subtract({ weeks: 1 }); // 2022-01-27T09:45[America/Los_Angeles]
date.subtract({ months: 1 }); // 2022-01-03T09:45[America/Los_Angeles]
date.subtract({ years: 1, months: 1, days: 1 }); // 2021-01-02T09:45[America/Los_Angeles]
date.subtract({ hours: 1 }); // 2022-02-03T8:45[America/Los_Angeles]
date.subtract({ minutes: 30 }); // 2022-02-03T09:15[America/Los_Angeles]
let date = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
date.add({ weeks: 1 }); // 2022-02-10T09:45[America/Los_Angeles]
date.add({ months: 1 }); // 2022-03-03T09:45[America/Los_Angeles]
date.add({ years: 1, months: 1, days: 1 }); // 2023-03-04T09:45[America/Los_Angeles]
date.add({ hours: 1 }); // 2022-02-03T10:45[America/Los_Angeles]
date.add({ minutes: 30 }); // 2022-02-03T10:15[America/Los_Angeles]
date.subtract({ weeks: 1 }); // 2022-01-27T09:45[America/Los_Angeles]
date.subtract({ months: 1 }); // 2022-01-03T09:45[America/Los_Angeles]
date.subtract({ years: 1, months: 1, days: 1 }); // 2021-01-02T09:45[America/Los_Angeles]
date.subtract({ hours: 1 }); // 2022-02-03T8:45[America/Los_Angeles]
date.subtract({ minutes: 30 }); // 2022-02-03T09:15[America/Los_Angeles]
let date =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
date.add({ weeks: 1 }); // 2022-02-10T09:45[America/Los_Angeles]
date.add({ months: 1 }); // 2022-03-03T09:45[America/Los_Angeles]
date.add({
years: 1,
months: 1,
days: 1
}); // 2023-03-04T09:45[America/Los_Angeles]
date.add({ hours: 1 }); // 2022-02-03T10:45[America/Los_Angeles]
date.add({
minutes: 30
}); // 2022-02-03T10:15[America/Los_Angeles]
date.subtract({
weeks: 1
}); // 2022-01-27T09:45[America/Los_Angeles]
date.subtract({
months: 1
}); // 2022-01-03T09:45[America/Los_Angeles]
date.subtract({
years: 1,
months: 1,
days: 1
}); // 2021-01-02T09:45[America/Los_Angeles]
date.subtract({
hours: 1
}); // 2022-02-03T8:45[America/Los_Angeles]
date.subtract({
minutes: 30
}); // 2022-02-03T09:15[America/Los_Angeles]
Adding or subtracting a duration that goes beyond the limits of a particular field will cause the date to be balanced. For example, adding one day to August 31st results in September 1st. In addition, if adding or subtracting one field causes another to be invalid, the date will be constrained. For example, adding one month to August 31st results in September 30th because September 31st does not exist.
Adding and subtracting is time zone aware. When adjusting a date around a daylight saving time transition, the hour may be adjusted accordingly. For example, in the United States, adding one hour during a "spring forward" transition skips the 2 AM hour, and adding an hour in a "fall back" transition repeats the 1 AM hour. Under the hood, the UTC offset is changing instead.
// A "spring forward" transition
let date = parseZonedDateTime('2020-03-08T01:00-08:00[America/Los_Angeles]');
date.add({hours: 1}); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "fall back" transition
let date = parseZonedDateTime('2020-11-01T01:00-07:00[America/Los_Angeles]');
date.add({hours: 1}); // 2020-11-01T01:00-08:00[America/Los_Angeles]
date.add({hours: 2}); // 2020-11-01T02:00-08:00[America/Los_Angeles]
// A "spring forward" transition
let date = parseZonedDateTime(
'2020-03-08T01:00-08:00[America/Los_Angeles]'
);
date.add({ hours: 1 }); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "fall back" transition
let date = parseZonedDateTime(
'2020-11-01T01:00-07:00[America/Los_Angeles]'
);
date.add({ hours: 1 }); // 2020-11-01T01:00-08:00[America/Los_Angeles]
date.add({ hours: 2 }); // 2020-11-01T02:00-08:00[America/Los_Angeles]
// A "spring forward" transition
let date =
parseZonedDateTime(
'2020-03-08T01:00-08:00[America/Los_Angeles]'
);
date.add({ hours: 1 }); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "fall back" transition
let date =
parseZonedDateTime(
'2020-11-01T01:00-07:00[America/Los_Angeles]'
);
date.add({ hours: 1 }); // 2020-11-01T01:00-08:00[America/Los_Angeles]
date.add({ hours: 2 }); // 2020-11-01T02:00-08:00[America/Los_Angeles]
In addition, when changing the date portion of a ZonedDateTime
around a daylight saving time transition, the hour may change if it is invalid in the target date. For example, during a "spring forward" transition, the 2 AM hour is skipped.
// A "spring forward" transition
let date = parseZonedDateTime('2020-03-07T02:00-08:00[America/Los_Angeles]');
date.add({days: 1}); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "spring forward" transition
let date = parseZonedDateTime(
'2020-03-07T02:00-08:00[America/Los_Angeles]'
);
date.add({ days: 1 }); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "spring forward" transition
let date =
parseZonedDateTime(
'2020-03-07T02:00-08:00[America/Los_Angeles]'
);
date.add({ days: 1 }); // 2020-03-08T03:00-07:00[America/Los_Angeles]
Setting fields#
ZonedDateTime
objects are immutable, which means their properties cannot be set directly. Instead, use the set
method, and pass the fields to be modified. This will return a new ZonedDateTime
with the updated values.
let date = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
date.set({ day: 10 }); // 2022-02-10T09:45[America/Los_Angeles]
date.set({ month: 5 }); // // 2022-05-03T09:45[America/Los_Angeles]
date.set({ year: 2023, month: 10, day: 16 }); // 2023-10-16T09:45[America/Los_Angeles]
date.set({ hour: 18 }); // 2022-02-03T18:45[America/Los_Angeles]
date.set({ minute: 15 }); // 2022-02-03T09:15[America/Los_Angeles]
let date = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
date.set({ day: 10 }); // 2022-02-10T09:45[America/Los_Angeles]
date.set({ month: 5 }); // // 2022-05-03T09:45[America/Los_Angeles]
date.set({ year: 2023, month: 10, day: 16 }); // 2023-10-16T09:45[America/Los_Angeles]
date.set({ hour: 18 }); // 2022-02-03T18:45[America/Los_Angeles]
date.set({ minute: 15 }); // 2022-02-03T09:15[America/Los_Angeles]
let date =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
date.set({ day: 10 }); // 2022-02-10T09:45[America/Los_Angeles]
date.set({ month: 5 }); // // 2022-05-03T09:45[America/Los_Angeles]
date.set({
year: 2023,
month: 10,
day: 16
}); // 2023-10-16T09:45[America/Los_Angeles]
date.set({ hour: 18 }); // 2022-02-03T18:45[America/Los_Angeles]
date.set({ minute: 15 }); // 2022-02-03T09:15[America/Los_Angeles]
Setting a field to a value that is outside the valid range will cause it to be constrained. For example, setting the day to a value that is greater than the number of days in the month, will result in the last day of the month.
let date = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
date.set({day: 100}); // 2022-02-28T09:45[America/Los_Angeles]
date.set({month: 20}); // 2022-12-03T09:45[America/Los_Angeles]
date.set({hour: 30}); // 2022-02-03T23:45[America/Los_Angeles]
let date = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
date.set({ day: 100 }); // 2022-02-28T09:45[America/Los_Angeles]
date.set({ month: 20 }); // 2022-12-03T09:45[America/Los_Angeles]
date.set({ hour: 30 }); // 2022-02-03T23:45[America/Los_Angeles]
let date =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
date.set({ day: 100 }); // 2022-02-28T09:45[America/Los_Angeles]
date.set({ month: 20 }); // 2022-12-03T09:45[America/Los_Angeles]
date.set({ hour: 30 }); // 2022-02-03T23:45[America/Los_Angeles]
Setting fields is time zone aware. When setting fields around a daylight saving time transition, the UTC offset will be adjusted accordingly. For example, when changing the day
field from before a daylight saving transition to after, the time remains the same but the UTC offset changes.
let date = parseZonedDateTime('2020-03-01T10:00-08:00[America/Los_Angeles]');
date.set({day: 14}); // 2020-03-14T10:00-07:00[America/Los_Angeles]
let date = parseZonedDateTime(
'2020-03-01T10:00-08:00[America/Los_Angeles]'
);
date.set({ day: 14 }); // 2020-03-14T10:00-07:00[America/Los_Angeles]
let date =
parseZonedDateTime(
'2020-03-01T10:00-08:00[America/Los_Angeles]'
);
date.set({ day: 14 }); // 2020-03-14T10:00-07:00[America/Los_Angeles]
In addition, some time values during daylight saving transitions may be ambiguous. For example, in the United States, the 2 AM hour is skipped in the spring, and the 1 AM hour occurs twice in the fall. When setting date fields, this ambiguity must be resolved to determine the exact time. By default, the later of the two possible times is chosen for "spring forward" transitions, and the earlier time is chosen for "fall back" transitions. This can be controlled by passing the disambiguation
parameter to the set
method.
'earlier'
– choose the earlier of the two possible times'later'
– choose the later of the two possible times'compatible'
(default) – choose the later of the two times during "spring forward" transitions, and the earlier time during "fall back" transitions.'reject'
– throws an error when the time is ambiguous
// A "spring forward" transition
let date = parseZonedDateTime('2020-03-01T02:00-08:00[America/Los_Angeles]');
date.set({ day: 8 }); // 2020-03-08T03:00:00-07:00[America/Los_Angeles]
date.set({ day: 8 }, 'earlier'); // 2020-03-08T01:00:00-08:00[America/Los_Angeles]
date.set({ day: 8 }, 'later'); // 2020-03-08T03:00:00-07:00[America/Los_Angeles]
// A "fall back" transition
let date = parseZonedDateTime('2020-10-01T01:00-07:00[America/Los_Angeles]');
date.set({ month: 11 }); // 2020-11-01T01:00:00-07:00[America/Los_Angeles]
date.set({ month: 11 }, 'earlier'); // 2020-11-01T01:00:00-07:00[America/Los_Angeles]
date.set({ month: 11 }, 'later'); // 2020-11-01T01:00:00-08:00[America/Los_Angeles]
// A "spring forward" transition
let date = parseZonedDateTime(
'2020-03-01T02:00-08:00[America/Los_Angeles]'
);
date.set({ day: 8 }); // 2020-03-08T03:00:00-07:00[America/Los_Angeles]
date.set({ day: 8 }, 'earlier'); // 2020-03-08T01:00:00-08:00[America/Los_Angeles]
date.set({ day: 8 }, 'later'); // 2020-03-08T03:00:00-07:00[America/Los_Angeles]
// A "fall back" transition
let date = parseZonedDateTime(
'2020-10-01T01:00-07:00[America/Los_Angeles]'
);
date.set({ month: 11 }); // 2020-11-01T01:00:00-07:00[America/Los_Angeles]
date.set({ month: 11 }, 'earlier'); // 2020-11-01T01:00:00-07:00[America/Los_Angeles]
date.set({ month: 11 }, 'later'); // 2020-11-01T01:00:00-08:00[America/Los_Angeles]
// A "spring forward" transition
let date =
parseZonedDateTime(
'2020-03-01T02:00-08:00[America/Los_Angeles]'
);
date.set({ day: 8 }); // 2020-03-08T03:00:00-07:00[America/Los_Angeles]
date.set(
{ day: 8 },
'earlier'
); // 2020-03-08T01:00:00-08:00[America/Los_Angeles]
date.set(
{ day: 8 },
'later'
); // 2020-03-08T03:00:00-07:00[America/Los_Angeles]
// A "fall back" transition
let date =
parseZonedDateTime(
'2020-10-01T01:00-07:00[America/Los_Angeles]'
);
date.set({ month: 11 }); // 2020-11-01T01:00:00-07:00[America/Los_Angeles]
date.set(
{ month: 11 },
'earlier'
); // 2020-11-01T01:00:00-07:00[America/Los_Angeles]
date.set(
{ month: 11 },
'later'
); // 2020-11-01T01:00:00-08:00[America/Los_Angeles]
Cycling fields#
The cycle
method allows incrementing or decrementing a single field. It is similar to the add
and subtract
methods, but when the value reaches the minimum or maximum, it wraps around rather than affecting other fields.
let date = parseZonedDateTime('2022-12-31T23:59[America/Los_Angeles]');
date.cycle('day', 1); // 2022-12-01T23:59[America/Los_Angeles]
date.cycle('month', 1); // 2022-01-31T23:59[America/Los_Angeles]
date.cycle('hour', 1); // 2022-12-31T00:59[America/Los_Angeles]
date.cycle('minute', 1); // 2022-12-31T23:00[America/Los_Angeles]
let date = parseZonedDateTime('2022-01-01T00:00[America/Los_Angeles]');
date.cycle('day', -1); // 2022-01-31T00:00[America/Los_Angeles]
date.cycle('month', -1); // 2022-12-01T00:00[America/Los_Angeles]
date.cycle('hour', -1); // 2022-01-01T23:00[America/Los_Angeles]
date.cycle('minute', -1); // 2022-01-01T00:59[America/Los_Angeles]
let date = parseZonedDateTime(
'2022-12-31T23:59[America/Los_Angeles]'
);
date.cycle('day', 1); // 2022-12-01T23:59[America/Los_Angeles]
date.cycle('month', 1); // 2022-01-31T23:59[America/Los_Angeles]
date.cycle('hour', 1); // 2022-12-31T00:59[America/Los_Angeles]
date.cycle('minute', 1); // 2022-12-31T23:00[America/Los_Angeles]
let date = parseZonedDateTime(
'2022-01-01T00:00[America/Los_Angeles]'
);
date.cycle('day', -1); // 2022-01-31T00:00[America/Los_Angeles]
date.cycle('month', -1); // 2022-12-01T00:00[America/Los_Angeles]
date.cycle('hour', -1); // 2022-01-01T23:00[America/Los_Angeles]
date.cycle('minute', -1); // 2022-01-01T00:59[America/Los_Angeles]
let date =
parseZonedDateTime(
'2022-12-31T23:59[America/Los_Angeles]'
);
date.cycle('day', 1); // 2022-12-01T23:59[America/Los_Angeles]
date.cycle('month', 1); // 2022-01-31T23:59[America/Los_Angeles]
date.cycle('hour', 1); // 2022-12-31T00:59[America/Los_Angeles]
date.cycle('minute', 1); // 2022-12-31T23:00[America/Los_Angeles]
let date =
parseZonedDateTime(
'2022-01-01T00:00[America/Los_Angeles]'
);
date.cycle('day', -1); // 2022-01-31T00:00[America/Los_Angeles]
date.cycle('month', -1); // 2022-12-01T00:00[America/Los_Angeles]
date.cycle('hour', -1); // 2022-01-01T23:00[America/Los_Angeles]
date.cycle('minute', -1); // 2022-01-01T00:59[America/Los_Angeles]
Note that if cycling a field causes another field to become invalid, the date is constrained. For example, adding one month to August 31st results in September 30th because September 31st does not exist.
The round
option may also be passed, which causes the value to be rounded to increments of the given amount. For example, you could round the minute to increments of 15.
let date = parseZonedDateTime('2022-02-03T09:22[America/Los_Angeles]');
date.cycle('minute', 15); // 2027-02-03T09:37[America/Los_Angeles]
date.cycle('minute', 15, { round: true }); // 2025-02-03T09:30[America/Los_Angeles]
date.cycle('minute', -15); // 2017-02-03T09:07[America/Los_Angeles]
date.cycle('minute', -15, { round: true }); // 2020-02-03T09:15[America/Los_Angeles]
let date = parseZonedDateTime(
'2022-02-03T09:22[America/Los_Angeles]'
);
date.cycle('minute', 15); // 2027-02-03T09:37[America/Los_Angeles]
date.cycle('minute', 15, { round: true }); // 2025-02-03T09:30[America/Los_Angeles]
date.cycle('minute', -15); // 2017-02-03T09:07[America/Los_Angeles]
date.cycle('minute', -15, { round: true }); // 2020-02-03T09:15[America/Los_Angeles]
let date =
parseZonedDateTime(
'2022-02-03T09:22[America/Los_Angeles]'
);
date.cycle('minute', 15); // 2027-02-03T09:37[America/Los_Angeles]
date.cycle(
'minute',
15,
{ round: true }
); // 2025-02-03T09:30[America/Los_Angeles]
date.cycle(
'minute',
-15
); // 2017-02-03T09:07[America/Los_Angeles]
date.cycle(
'minute',
-15,
{ round: true }
); // 2020-02-03T09:15[America/Los_Angeles]
By default, the hour
field is cycled within a 24 hour range. The hourCycle
option can be set to 12
to use a 12 hour clock instead, which will preserve the AM/PM value when formatted.
let date = parseZonedDateTime('2022-02-03T11:00[America/Los_Angeles]');
date.cycle('hour', 1); // 2022-02-03T12:00[America/Los_Angeles]
date.cycle('hour', 1, {hourCycle: 12}); // 2022-02-03T00:00[America/Los_Angeles]
let date = parseZonedDateTime('2022-02-03T23:00[America/Los_Angeles]');
date.cycle('hour', 1); // 2022-02-03T00:00[America/Los_Angeles]
date.cycle('hour', 1, {hourCycle: 12}); // 2022-02-03T12:00[America/Los_Angeles]
let date = parseZonedDateTime(
'2022-02-03T11:00[America/Los_Angeles]'
);
date.cycle('hour', 1); // 2022-02-03T12:00[America/Los_Angeles]
date.cycle('hour', 1, { hourCycle: 12 }); // 2022-02-03T00:00[America/Los_Angeles]
let date = parseZonedDateTime(
'2022-02-03T23:00[America/Los_Angeles]'
);
date.cycle('hour', 1); // 2022-02-03T00:00[America/Los_Angeles]
date.cycle('hour', 1, { hourCycle: 12 }); // 2022-02-03T12:00[America/Los_Angeles]
let date =
parseZonedDateTime(
'2022-02-03T11:00[America/Los_Angeles]'
);
date.cycle('hour', 1); // 2022-02-03T12:00[America/Los_Angeles]
date.cycle('hour', 1, {
hourCycle: 12
}); // 2022-02-03T00:00[America/Los_Angeles]
let date =
parseZonedDateTime(
'2022-02-03T23:00[America/Los_Angeles]'
);
date.cycle('hour', 1); // 2022-02-03T00:00[America/Los_Angeles]
date.cycle('hour', 1, {
hourCycle: 12
}); // 2022-02-03T12:00[America/Los_Angeles]
Cycling fields is time zone aware. When adjusting a date around a daylight saving time transition, the hour may be adjusted accordingly. For example, in the United States, adding one hour during a "spring forward" transition skips the 2 AM hour, and adding an hour in a "fall back" transition repeats the 1 AM hour. Under the hood, the UTC offset is changing instead.
// A "spring forward" transition
let date = parseZonedDateTime('2020-03-08T01:00-08:00[America/Los_Angeles]');
date.cycle('hour', 1); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "fall back" transition
let date = parseZonedDateTime('2020-11-01T01:00-07:00[America/Los_Angeles]');
date.cycle('hour', 1); // 2020-11-01T01:00-08:00[America/Los_Angeles]
// A "spring forward" transition
let date = parseZonedDateTime(
'2020-03-08T01:00-08:00[America/Los_Angeles]'
);
date.cycle('hour', 1); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "fall back" transition
let date = parseZonedDateTime(
'2020-11-01T01:00-07:00[America/Los_Angeles]'
);
date.cycle('hour', 1); // 2020-11-01T01:00-08:00[America/Los_Angeles]
// A "spring forward" transition
let date =
parseZonedDateTime(
'2020-03-08T01:00-08:00[America/Los_Angeles]'
);
date.cycle('hour', 1); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "fall back" transition
let date =
parseZonedDateTime(
'2020-11-01T01:00-07:00[America/Los_Angeles]'
);
date.cycle('hour', 1); // 2020-11-01T01:00-08:00[America/Los_Angeles]
In addition, when changing the date portion of a ZonedDateTime
around a daylight saving time transition, the hour may change if it is invalid in the target date. For example, during a "spring forward" transition, the 2 AM hour is skipped.
// A "spring forward" transition
let date = parseZonedDateTime('2020-03-07T02:00-08:00[America/Los_Angeles]');
date.cycle('day', 1); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "spring forward" transition
let date = parseZonedDateTime(
'2020-03-07T02:00-08:00[America/Los_Angeles]'
);
date.cycle('day', 1); // 2020-03-08T03:00-07:00[America/Los_Angeles]
// A "spring forward" transition
let date =
parseZonedDateTime(
'2020-03-07T02:00-08:00[America/Los_Angeles]'
);
date.cycle('day', 1); // 2020-03-08T03:00-07:00[America/Los_Angeles]
Conversion#
To a string#
ZonedDateTime
objects can be converted to an ISO 8601 formatted string using the toString
method. This format preserves the maximum amount of information, including the UTC offset and time zone identifier, in the same format used in other languages like Java.
let date = new ZonedDateTime(
2022, 2, 3,
'America/Los_Angeles', -28800000,
12, 24, 45
);
date.toString(); // '2022-02-03T12:24:45-08:00[America/Los_Angeles]'
let date = new ZonedDateTime(
2022,
2,
3,
'America/Los_Angeles',
-28800000,
12,
24,
45
);
date.toString(); // '2022-02-03T12:24:45-08:00[America/Los_Angeles]'
let date =
new ZonedDateTime(
2022,
2,
3,
'America/Los_Angeles',
-28800000,
12,
24,
45
);
date.toString(); // '2022-02-03T12:24:45-08:00[America/Los_Angeles]'
If the exact local time and time zone that a user selected is important, use this format. Storing the time zone and offset that was selected rather than converting to UTC ensures that the local time is correct regardless of daylight saving rule changes (e.g. if a locale abolishes DST). Examples where this applies include calendar events, reminders, and other times that occur in a particular location.
You can also use the toAbsoluteString
method to convert the date to a UTC string. Use this format if the exact time no matter the time zone is needed.
date.toAbsoluteString(); // '2022-02-03T20:24:45.000Z'
date.toAbsoluteString(); // '2022-02-03T20:24:45.000Z'
date.toAbsoluteString(); // '2022-02-03T20:24:45.000Z'
To a native Date object#
A ZonedDateTime
can be converted to a native JavaScript Date
object using the toDate
method. In general, the Date
object should be avoided because it has many internationalization issues and other flaws. However, it is necessary to use some functionality like date formatting.
let date = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
date.toDate('America/Los_Angeles'); // Thu Feb 03 2022 09:45:00 GMT-0800 (Pacific Standard Time)
let date = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
date.toDate('America/Los_Angeles'); // Thu Feb 03 2022 09:45:00 GMT-0800 (Pacific Standard Time)
let date =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
date.toDate(
'America/Los_Angeles'
); // Thu Feb 03 2022 09:45:00 GMT-0800 (Pacific Standard Time)
To a date or time only#
A ZonedDateTime
can be converted to a CalendarDate or Time object if only one of these components is needed.
Use the toCalendarDate
function to convert a ZonedDateTime
to a CalendarDate
.
import {toCalendarDate} from '@internationalized/date';
let date = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
toCalendarDate(date); // 2022-02-03
import {toCalendarDate} from '@internationalized/date';
let date = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
toCalendarDate(date); // 2022-02-03
import {toCalendarDate} from '@internationalized/date';
let date =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
toCalendarDate(date); // 2022-02-03
Use the toTime
function to convert a ZonedDateTime
to a Time
.
import {toTime} from '@internationalized/date';
let date = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
toTime(date); // 09:45
import {toTime} from '@internationalized/date';
let date = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
toTime(date); // 09:45
import {toTime} from '@internationalized/date';
let date =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
toTime(date); // 09:45
To a date and time without a time zone#
A ZonedDateTime
can be converted to a CalendarDateTime, which represents a date and time that is not in any specific time zone. Use this type to represent times that occur at the same local time regardless of the time zone, such as the time of New Years Eve fireworks which always occur at midnight. Most times are better stored as a ZonedDateTime
.
Use the toCalendarDateTime
function to convert a ZonedDateTime
to a CalendarDateTime
.
import {toCalendarDateTime} from '@internationalized/date';
let date = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
toCalendarDateTime(date); // 2022-02-03T09:45:00
import {toCalendarDateTime} from '@internationalized/date';
let date = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
toCalendarDateTime(date); // 2022-02-03T09:45:00
import {toCalendarDateTime} from '@internationalized/date';
let date =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
toCalendarDateTime(date); // 2022-02-03T09:45:00
Between time zones#
A ZonedDateTime
can be converted to a different time zone using the toTimeZone
function. The toLocalTimeZone
function can also be used to convert to the current user's local time zone.
import {toTimeZone, toLocalTimeZone} from '@internationalized/date';
let date = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
toTimeZone(date, 'America/Chicago'); // 2022-02-03T11:45[America/Chicago]
toLocalTimeZone(date); // e.g. 2022-02-03T12:45[America/New_York]
import {
toLocalTimeZone,
toTimeZone
} from '@internationalized/date';
let date = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
toTimeZone(date, 'America/Chicago'); // 2022-02-03T11:45[America/Chicago]
toLocalTimeZone(date); // e.g. 2022-02-03T12:45[America/New_York]
import {
toLocalTimeZone,
toTimeZone
} from '@internationalized/date';
let date =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
toTimeZone(
date,
'America/Chicago'
); // 2022-02-03T11:45[America/Chicago]
toLocalTimeZone(date); // e.g. 2022-02-03T12:45[America/New_York]
Queries#
Comparison#
ZonedDateTime
objects can be compared either for full or partial equality, or in order to determine which date is before or after another.
The compare
method can be used to determine if a date is before or after another. It returns a number less than zero if the first date is before the second, zero if the values are equal, or a number greater than zero if the first date is after the second.
let a = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
let b = parseZonedDateTime('2022-03-04T09:45[America/Los_Angeles]');
a.compare(b) < 0; // true
b.compare(a) > 0; // true
let a = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
let b = parseZonedDateTime(
'2022-03-04T09:45[America/Los_Angeles]'
);
a.compare(b) < 0; // true
b.compare(a) > 0; // true
let a =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
let b =
parseZonedDateTime(
'2022-03-04T09:45[America/Los_Angeles]'
);
a.compare(b) < 0; // true
b.compare(a) > 0; // true
In addition, the following functions can be used to perform a partial comparison. These functions accept dates in different calendar systems, and the second date is converted to the calendar system of the first date before comparison.
isSameYear
– Returns whether the given dates occur in the same year, using the calendar system of the first date.isSameMonth
– Returns whether the given dates occur in the same month, using the calendar system of the first date.isSameDay
– Returns whether the given dates occur on the same day, regardless of the time or calendar system.isToday
– Returns whether the date is today in the given time zone.
import {isSameMonth} from '@internationalized/date';
isSameMonth(
parseZonedDateTime('2022-04-16T09:45[America/Los_Angeles]'),
parseZonedDateTime('2022-04-30T05:15[America/Los_Angeles]'),
); // true
isSameMonth(
parseZonedDateTime('2022-04-16T09:45[America/Los_Angeles]'),
parseZonedDateTime('2022-08-020T05:15[America/Los_Angeles]'),
); // false
import {isSameMonth} from '@internationalized/date';
isSameMonth(
parseZonedDateTime(
'2022-04-16T09:45[America/Los_Angeles]'
),
parseZonedDateTime(
'2022-04-30T05:15[America/Los_Angeles]'
)
); // true
isSameMonth(
parseZonedDateTime(
'2022-04-16T09:45[America/Los_Angeles]'
),
parseZonedDateTime(
'2022-08-020T05:15[America/Los_Angeles]'
)
); // false
import {isSameMonth} from '@internationalized/date';
isSameMonth(
parseZonedDateTime(
'2022-04-16T09:45[America/Los_Angeles]'
),
parseZonedDateTime(
'2022-04-30T05:15[America/Los_Angeles]'
)
); // true
isSameMonth(
parseZonedDateTime(
'2022-04-16T09:45[America/Los_Angeles]'
),
parseZonedDateTime(
'2022-08-020T05:15[America/Los_Angeles]'
)
); // false
A similar set of functions is also available that does not convert between calendar systems and requires the calendars to be equal.
isEqualYear
– Returns whether the given dates occur in the same year, and are of the same calendar system.isEqualMonth
– Returns whether the given dates occur in the same month, and are of the same calendar system.isEqualDay
– Returns whether the given dates occur on the same day, and are of the same calendar system.
Start and end dates#
The following functions can be used to find the start or end dates of a particular unit of time. These only affect the date components of a ZonedDateTime
. The time fields are left unchanged.
startOfYear
– Returns the first day of the year for the given date.endOfYear
– Returns the last day of the year for the given date.startOfMonth
– Returns the first date of the month for the given date.endOfMonth
– Returns the last date of the month for the given date.startOfWeek
– Returns the first date of the week for the given date and locale.endOfWeek
– Returns the last date of the week for the given date and locale.
Note that startOfWeek
and endOfWeek
require a locale string to be provided. This is because the first day of the week changes depending on the locale. For example, in the United States, the first day of the week is on Sunday, but in France it is on Monday.
import {startOfYear, startOfMonth, startOfWeek} from '@internationalized/date';
let date = parseZonedDateTime('2022-02-03T09:45[America/Los_Angeles]');
startOfYear(date); // 2022-01-01T09:45[America/Los_Angeles]
startOfMonth(date); // 2022-02-01T09:45[America/Los_Angeles]
startOfWeek(date, 'en-US'); // 2022-01-30T09:45[America/Los_Angeles]
startOfWeek(date, 'fr-FR'); // 2022-01-31T09:45[America/Los_Angeles]
import {
startOfMonth,
startOfWeek,
startOfYear
} from '@internationalized/date';
let date = parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
startOfYear(date); // 2022-01-01T09:45[America/Los_Angeles]
startOfMonth(date); // 2022-02-01T09:45[America/Los_Angeles]
startOfWeek(date, 'en-US'); // 2022-01-30T09:45[America/Los_Angeles]
startOfWeek(date, 'fr-FR'); // 2022-01-31T09:45[America/Los_Angeles]
import {
startOfMonth,
startOfWeek,
startOfYear
} from '@internationalized/date';
let date =
parseZonedDateTime(
'2022-02-03T09:45[America/Los_Angeles]'
);
startOfYear(date); // 2022-01-01T09:45[America/Los_Angeles]
startOfMonth(date); // 2022-02-01T09:45[America/Los_Angeles]
startOfWeek(
date,
'en-US'
); // 2022-01-30T09:45[America/Los_Angeles]
startOfWeek(
date,
'fr-FR'
); // 2022-01-31T09:45[America/Los_Angeles]
Day of week#
The getDayOfWeek
function returns the day of the week for the given date and locale. Days are numbered from zero to six, where zero is the first day of the week in the given locale. For example, in the United States, the first day of the week is Sunday, but in France it is Monday.
import {getDayOfWeek} from '@internationalized/date';
let date = parseZonedDateTime('2022-02-06T08:30[America/Los_Angeles]'); // a Sunday
getDayOfWeek(date, 'en-US'); // 0
getDayOfWeek(locale, 'fr-FR'); // 6
import {getDayOfWeek} from '@internationalized/date';
let date = parseZonedDateTime(
'2022-02-06T08:30[America/Los_Angeles]'
); // a Sunday
getDayOfWeek(date, 'en-US'); // 0
getDayOfWeek(locale, 'fr-FR'); // 6
import {getDayOfWeek} from '@internationalized/date';
let date =
parseZonedDateTime(
'2022-02-06T08:30[America/Los_Angeles]'
); // a Sunday
getDayOfWeek(
date,
'en-US'
); // 0
getDayOfWeek(
locale,
'fr-FR'
); // 6
Weekdays and weekends#
The isWeekday
and isWeekend
functions can be used to determine if a date is weekday or weekend respectively. This depends on the locale. For example, in the United States, weekends are Saturday and Sunday, but in Israel they are Friday and Saturday.
import {isWeekday, isWeekend} from '@internationalized/date';
let date = parseZonedDateTime('2022-02-06T08:30[America/Los_Angeles]'); // a Sunday
isWeekday(date, 'en-US'); // false
isWeekday(date, 'he-IL'); // true
isWeekend(date, 'en-US'); // true
isWeekday(date, 'he-IL'); // false
import {
isWeekday,
isWeekend
} from '@internationalized/date';
let date = parseZonedDateTime(
'2022-02-06T08:30[America/Los_Angeles]'
); // a Sunday
isWeekday(date, 'en-US'); // false
isWeekday(date, 'he-IL'); // true
isWeekend(date, 'en-US'); // true
isWeekday(date, 'he-IL'); // false
import {
isWeekday,
isWeekend
} from '@internationalized/date';
let date =
parseZonedDateTime(
'2022-02-06T08:30[America/Los_Angeles]'
); // a Sunday
isWeekday(date, 'en-US'); // false
isWeekday(date, 'he-IL'); // true
isWeekend(date, 'en-US'); // true
isWeekday(date, 'he-IL'); // false
Weeks in month#
The getWeeksInMonth
function returns the number of weeks in the given month. This depends on the number of days in the month, what day of the week the month starts on, and the given locale. For example, in the United States, the first day of the week is Sunday, but in France it is Monday.
import {getWeeksInMonth} from '@internationalized/date';
let date = parseZonedDateTime('2022-01-01T08:30[America/Los_Angeles]');
getWeeksInMonth(date, 'en-US'); // 6
getWeeksInMonth(date, 'fr-FR'); // 5
import {getWeeksInMonth} from '@internationalized/date';
let date = parseZonedDateTime(
'2022-01-01T08:30[America/Los_Angeles]'
);
getWeeksInMonth(date, 'en-US'); // 6
getWeeksInMonth(date, 'fr-FR'); // 5
import {getWeeksInMonth} from '@internationalized/date';
let date =
parseZonedDateTime(
'2022-01-01T08:30[America/Los_Angeles]'
);
getWeeksInMonth(
date,
'en-US'
); // 6
getWeeksInMonth(
date,
'fr-FR'
); // 5