Temporal
Базовый уровень Ограниченная доступность
Эта функция не является Базовым уровнем, потому что она не работает в некоторых наиболее широко используемых браузерах.
Объект Temporal обеспечивает управление датой и временем в различных сценариях, включая встроенное представление часовых поясов и календарей, преобразования времени по часам на стене, арифметические операции, форматирование и многое другое. Он разработан как полная замена для объекта Date.
Описание
В отличие от большинства глобальных объектов, Temporal не является конструктором. Вы не можете использовать его с оператором new или вызывать объект Temporal как функцию. Все свойства и методы Temporal являются статическими (так же, как и объект Math).
Temporal имеет сложный и мощный API. Он предоставляет более 200 вспомогательных методов через несколько классов, поэтому может показаться очень сложным. Мы предоставим обзор высокого уровня того, как эти API связаны друг с другом.
Предыстория и концепции
В JavaScript объект Date для обработки даты и времени существует с самого начала. Однако API Date основан на плохо спроектированном классе java.util.Date из Java, который был заменен в начале 2010-х годов; но из-за цели JavaScript по обеспечению обратной совместимости, Date остается в языке.
Важный урок, которым стоит предварить все введение, заключается в том, что обработка дат сложна. Большинство проблем Date можно исправить, добавив больше методов, но фундаментальный недостаток дизайна остается: он предоставляет так много методов в одном и том же объекте, что разработчики часто путаются в том, что использовать, что приводит к неожиданным ошибкам. Хорошо спроектированный API должен не только делать больше, но и делать меньше на каждом уровне абстракции, поскольку предотвращение неправильного использования так же важно, как и обеспечение вариантов использования.
Объекты Date одновременно выполняют две функции:
- Как метка времени: количество миллисекунд или наносекунд, прошедших с фиксированной точки времени (известной как эпоха).
- Как комбинация компонентов: год, месяц, день, час, минута, секунда, миллисекунда и наносекунда. Идентификаторы года, месяца и дня имеют смысл только применительно к календарной системе. Вся комбинация соответствует уникальному моменту в истории, если она связана с часовым поясом. Объекты
Dateпредоставляют методы для чтения и изменения этих компонентов.
Часовые пояса лежат в основе значительного числа ошибок, связанных с датами. При взаимодействии с Date через модель «комбинации компонентов» время может быть только в двух часовых поясах: UTC и локальном (устройство), и нет возможности указать произвольный часовой пояс. Также отсутствует концепция «без часового пояса»: это известно как календарная дата (для дат) или время по часам на стене (для времени), то есть время, которое вы «считываете с календаря или часов». Например, если вы устанавливаете ежедневный будильник, вы захотите установить его на «8:00AM» независимо от того, является ли это летним временем или нет, путешествовали ли вы в другой часовой пояс и т. д.
Вторая функция, отсутствующая в Date, — это календарная система. Большинство людей, вероятно, знакомы с григорианским календарем, где есть две эры, до н. э. и н. э.; есть 12 месяцев; в каждом месяце разное количество дней; високосный год бывает каждые 4 года; и так далее. Однако некоторые из этих понятий могут не применяться, когда вы работаете с другой календарной системой, такой как еврейский календарь, китайский календарь, японский календарь и т. д. С Date вы можете работать только с моделью григорианского календаря.
Есть много других нежелательных наследий Date, например, то, что все сеттеры являются мутирующими (что часто вызывает нежелательные побочные эффекты), формат строки даты и времени невозможно проанализировать согласованным образом и т. д. В конце концов, лучшее решение — создать новый API с нуля, которым и является Temporal.
Обзор API
Temporal — это пространство имен, как и Intl. Оно содержит несколько классов и пространств имен, каждое из которых предназначено для обработки определенного аспекта управления датой и временем. Классы могут быть сгруппированы следующим образом:
- Представление продолжительности времени (разница между двумя моментами времени):
Temporal.Duration - Представление момента времени:
- Представление уникального момента в истории:
- Как метка времени:
Temporal.Instant - Как комбинация компонентов даты-времени в паре с часовым поясом:
Temporal.ZonedDateTime
- Как метка времени:
- Представление даты/времени, не зависящего от часового пояса (все они имеют префикс "Plain"):
- Дата (год, месяц, день) + время (час, минута, секунда, миллисекунда, микросекунда, наносекунда):
Temporal.PlainDateTime(Примечание:ZonedDateTimeэквивалентенPlainDateTimeплюс часовой пояс)- Дата (год, месяц, день):
Temporal.PlainDate- Год, месяц:
Temporal.PlainYearMonth - Месяц, день:
Temporal.PlainMonthDay
- Год, месяц:
- Время (час, минута, секунда, миллисекунда, микросекунда, наносекунда):
Temporal.PlainTime
- Дата (год, месяц, день):
- Дата (год, месяц, день) + время (час, минута, секунда, миллисекунда, микросекунда, наносекунда):
- Представление уникального момента в истории:
Кроме того, существует еще одно вспомогательное пространство имен, Temporal.Now, которое предоставляет методы для получения текущего времени в различных форматах.
Общий интерфейс класса
В пространстве имен Temporal много классов, но они имеют много общих методов. В следующей таблице перечислены все методы каждого класса (кроме методов преобразования):
В следующей таблице приводится сводка того, какие свойства доступны в каждом классе, что дает вам представление о том, какую информацию может представлять каждый класс.
Преобразование между классами
В таблице ниже приведена сводка всех методов преобразования, которые существуют в каждом классе.
| Как преобразовать из... | ||||||||
Instant | ZonedDateTime | PlainDateTime | PlainDate | PlainTime | PlainYearMonth | PlainMonthDay | ||
|---|---|---|---|---|---|---|---|---|
| в... | Instant |
/ | toInstant() |
Сначала преобразуйте в ZonedDateTime |
||||
ZonedDateTime |
toZonedDateTimeISO() |
/ | toZonedDateTime() |
toZonedDateTime() |
PlainDate#toZonedDateTime() (передается как аргумент) |
Сначала преобразуйте в PlainDate |
||
PlainDateTime |
Сначала преобразуйте в ZonedDateTime |
toPlainDateTime() |
/ | toPlainDateTime() |
PlainDate#toPlainDateTime() (передается как аргумент) |
|||
PlainDate |
toPlainDate() |
toPlainDate() |
/ | Нет пересечения информации | toPlainDate() |
toPlainDate() |
||
PlainTime |
toPlainTime() |
toPlainTime() |
Нет пересечения информации | / | Нет пересечения информации | |||
PlainYearMonth |
Сначала преобразуйте в PlainDate |
toPlainYearMonth() |
Нет пересечения информации | / | Сначала преобразуйте в PlainDate |
|||
PlainMonthDay |
toPlainMonthDay() |
Сначала преобразуйте в PlainDate |
/ | |||||
С помощью этих таблиц вы должны получить базовое представление о том, как ориентироваться в API Temporal.
Календари
Календарь — это способ организации дней, обычно в периоды недель, месяцев, лет и эр. Большая часть мира использует григорианский календарь, но существует множество других календарей, используемых, особенно в религиозных и культурных контекстах. По умолчанию все объекты Temporal, учитывающие календарь, используют календарную систему ISO 8601, которая основана на григорианском календаре и определяет дополнительные правила нумерации недель. Intl.supportedValuesOf() перечисляет большинство календарей, которые, вероятно, поддерживаются браузерами. Здесь мы приводим краткий обзор того, как формируются календарные системы, чтобы помочь вам понять, какие факторы могут различаться в разных календарях.
На Земле происходит три основных периодических события: ее вращение вокруг Солнца (365,242 дня за один оборот), вращение Луны вокруг Земли (29,53 дня от новолуния до новолуния) и ее вращение вокруг своей оси (24 часа от восхода до восхода). Каждая культура имеет одну и ту же меру «дня» — 24 часа. Эпизодические изменения, такие как переход на летнее время, не являются частью календаря, но являются частью информации о часовом поясе.
- Некоторые календари в первую очередь определяют один год как в среднем 365,242 дня, определяя, что годы имеют 365 дней, и добавляя дополнительный день, високосный день, примерно каждые 4 года. Затем год может быть далее разделен на части, называемые месяцами. Эти календари называются солнечными календарями. Григорианский календарь и Солнечный календарь Хиджры являются солнечными календарями.
- Некоторые календари в первую очередь определяют один месяц как в среднем 29,5 дня, определяя, что месяцы чередуются между 29 и 30 днями. Затем 12 месяцев могут быть сгруппированы в год, состоящий из 354 дней. Эти календари называются лунными календарями. Исламский календарь является лунным календарем. Поскольку лунный год является искусственным и не коррелирует с циклом сезонов, лунные календари, как правило, встречаются реже.
- Некоторые календари также в первую очередь определяют месяцы на основе лунных циклов, как лунные календари. Затем, чтобы компенсировать 11-дневное расхождение с солнечным годом, примерно каждые 3 года добавляется дополнительный месяц, високосный месяц. Эти календари называются лунно-солнечными календарями. Еврейский календарь и китайский календарь являются лунно-солнечными календарями.
В Temporal каждая дата в рамках одной календарной системы однозначно идентифицируется тремя компонентами: year, month и day. Хотя year обычно является положительным целым числом, оно также может быть нулевым или отрицательным и монотонно увеличивается со временем. Год 1 (или 0, если он существует) известен как календарная эпоха и является произвольным для каждого календаря. month — это положительное целое число, которое увеличивается на 1 каждый раз, начиная с 1 и заканчивая date.monthsInYear, а затем сбрасывается до 1 по мере продвижения года. day также является положительным целым числом, но оно может начинаться не с 1 и не увеличиваться на 1 каждый раз, поскольку политические изменения могут привести к пропуску или повторению дней. Но в целом day монотонно увеличивается и сбрасывается по мере продвижения месяца.
В дополнение к year, год также может быть однозначно идентифицирован комбинацией era и eraYear для календарей, использующих эры. Например, григорианский календарь использует эры «CE» (Common Era — Наша эра) и «BCE» (Before Common Era — До нашей эры), а год -1 совпадает с { era: "bce", eraYear: 2 } (обратите внимание, что год 0 всегда существует для всех календарей; для григорианского календаря он соответствует 1 году до н. э. из-за астрономической нумерации года). era — это строка в нижнем регистре, а eraYear — это произвольное целое число, которое может быть нулевым, отрицательным или даже уменьшаться со временем (обычно для самой старой эры).
Примечание: Всегда используйте era и eraYear в паре; не используйте одно свойство без использования другого. Кроме того, чтобы избежать конфликтов, не комбинируйте year и era/eraYear при обозначении года. Выберите одно представление года и используйте его последовательно.
Остерегайтесь следующих неверных предположений о годах:
- Не предполагайте, что
eraиeraYearвсегда присутствуют; они могут бытьundefined. - Не предполагайте, что
era— это удобная для пользователя строка; используйтеtoLocaleString()для форматирования даты. - Не предполагайте, что два значения
yearиз разных календарей сопоставимы; вместо этого используйте статический методcompare(). - Не предполагайте, что в годах 365/366 дней и 12 месяцев; используйте
daysInYearиmonthsInYearвместо этого. - Не предполагайте, что високосные годы (
inLeapYear— этоtrue) имеют один дополнительный день; у них может быть дополнительный месяц.
В дополнение к month, месяц в году также может быть однозначно идентифицирован с помощью monthCode. monthCode обычно соответствует названию месяца, а month — нет. Например, в случае лунно-солнечных календарей два месяца с одинаковым monthCode, один из которых принадлежит високосному году, а другой нет, будут иметь разные значения month, если они идут после високосного месяца, из-за вставки дополнительного месяца.
Примечание: Во избежание конфликтов не совмещайте month и monthCode при обозначении месяца. Выберите одно представление месяца и используйте его последовательно. month более полезен, если вам нужен порядок месяцев в году (например, при переборе месяцев), в то время как monthCode более полезен, если вам нужно имя месяца (например, при хранении дат рождения).
Будьте осторожны со следующими неверными предположениями о месяцах:
- Не предполагайте, что
monthCodeиmonthвсегда соответствуют друг другу. - Не предполагайте количество дней в месяце; используйте
daysInMonthвместо этого. - Не предполагайте, что
monthCodeявляется удобной для пользователя строкой; используйтеtoLocaleString()для форматирования даты вместо этого. - В целом, не кэшируйте названия месяцев в массиве или объекте. Хотя
monthCodeобычно сопоставляется с названием месяца в рамках одного календаря, мы рекомендуем всегда вычислять название месяца, используя, например,date.toLocaleString("en-US", { calendar: date.calendarId, month: "long" }).
В дополнение к day (который является индексом, основанным на месяце), день в году также может быть однозначно идентифицирован с помощью dayOfYear. dayOfYear — это положительное целое число, которое каждый раз увеличивается на 1, начиная с 1 и заканчивая date.daysInYear.
Концепция «недели» не связана ни с каким астрономическим событием, а является культурным конструктом. Хотя наиболее распространенная длина составляет 7 дней, недели также могут иметь 4, 5, 6, 8 или более дней — или даже вообще не иметь фиксированного числа дней. Чтобы получить конкретное число дней недели для даты, используйте daysInWeek этой даты. Temporal идентифицирует недели по комбинации weekOfYear и yearOfWeek. weekOfYear — это положительное целое число, которое каждый раз увеличивается на 1, начиная с 1, затем сбрасывается до 1 по мере смены года. yearOfWeek в целом совпадает с year, но может отличаться в начале или конце каждого года, поскольку одна неделя может пересекать два года, и yearOfWeek выбирает один из двух годов на основе правил календаря.
Примечание: Всегда используйте weekOfYear и yearOfWeek в паре; не используйте weekOfYear и year.
Будьте осторожны со следующими неверными предположениями о неделях:
- Не предполагайте, что
weekOfYearиyearOfWeekвсегда присутствуют; они могут бытьundefined. - Не предполагайте, что недели всегда длятся 7 дней; используйте
daysInWeekвместо этого. - Обратите внимание, что текущий API
Temporalне поддерживает даты в формате год-неделя, поэтому вы не можете создавать даты, используя эти свойства, или сериализовать даты в представления год-неделя. Они являются только информационными свойствами.
Формат RFC 9557
Все классы Temporal могут быть сериализованы и десериализованы с использованием формата, указанного в RFC 9557, который основан на ISO 8601 / RFC 3339. Формат в полной форме выглядит следующим образом (пробелы предназначены только для удобства чтения и не должны присутствовать в фактической строке):
YYYY-MM-DD T HH:mm:ss.sssssssss Z/±HH:mm [time_zone_id] [u-ca=calendar_id]
Различные классы имеют разные требования к присутствию каждого компонента, поэтому вы найдете раздел под названием «Формат RFC 9557» в документации каждого класса, который определяет формат, распознаваемый этим классом.
Это очень похоже на формат строки даты и времени, используемый Date, который также основан на ISO 8601. Основное дополнение — это возможность указывать компоненты микро- и наносекунд, а также возможность указывать часовой пояс и систему календаря.
Представимые даты
Все объекты Temporal, представляющие определенную календарную дату, налагают аналогичное ограничение на диапазон представимых дат, который составляет ±108 дней (включительно) от эпохи Unix, или диапазон мгновений от -271821-04-20T00:00:00 до +275760-09-13T00:00:00. Это тот же диапазон, что и у действительных дат. Более конкретно:
-
Temporal.InstantиTemporal.ZonedDateTimeприменяют это ограничение непосредственно к его значениюepochNanoseconds. -
Temporal.PlainDateTimeинтерпретирует дату-время в часовом поясе UTC и требует, чтобы она находилась в пределах ±(108 + 1) дней (исключая) от эпохи Unix, поэтому ее допустимый диапазон — от-271821-04-19T00:00:00до+275760-09-14T00:00:00, не включая границы. Это позволяет любомуZonedDateTimeбыть преобразованным вPlainDateTimeнезависимо от его смещения. -
Temporal.PlainDateприменяет ту же проверку, что иPlainDateTime, к полудню (12:00:00) этой даты, поэтому его допустимый диапазон — от-271821-04-19до+275760-09-13. Это позволяет любомуPlainDateTimeбыть преобразованным вPlainDateнезависимо от его времени, и наоборот. -
Temporal.PlainYearMonthимеет допустимый диапазон от-271821-04до+275760-09. Это позволяет любомуPlainDateбыть преобразованным вPlainYearMonthнезависимо от его даты (за исключением случаев, когда первый день неизолированного месяца попадает в ISO-месяц-271821-03).
Объекты Temporal откажутся создавать экземпляр, представляющий дату/время за пределами этого ограничения. Сюда входит:
- Использование конструктора или статического метода
from(). - Использование метода
with()для обновления полей календаря. - Использование
add(),subtract(),round()или любого другого метода для получения новых экземпляров.
Статические свойства
-
Temporal.Duration - Представляет разницу между двумя моментами времени, которую можно использовать в арифметике даты/времени. По сути, он представлен как комбинация значений лет, месяцев, недель, дней, часов, минут, секунд, миллисекунд, микросекунд и наносекунд.
-
Temporal.Instant - Представляет уникальный момент времени с наносекундной точностью. По сути, он представлен как количество наносекунд, прошедших с эпохи Unix (полночь 1 января 1970 года по UTC), без какого-либо часового пояса или системы календаря.
-
Temporal.Now - Предоставляет методы для получения текущего времени в различных форматах.
-
Temporal.PlainDate - Представляет календарную дату (дату без времени или часового пояса); например, событие в календаре, которое происходит в течение всего дня, независимо от того, в каком часовом поясе оно происходит. По сути, он представлен как календарная дата ISO 8601 с полями года, месяца и дня и связанной с ней системой календаря.
-
Temporal.PlainDateTime - Представляет дату (календарную дату) и время (настенное время) без часового пояса. По сути, он представлен как комбинация даты (со связанной системой календаря) и времени.
-
Temporal.PlainMonthDay - Представляет месяц и день календарной даты, без года или часового пояса; например, событие в календаре, которое повторяется каждый год и происходит в течение всего дня. По сути, он представлен как календарная дата ISO 8601 с полями года, месяца и дня и связанной с ней системой календаря. Год используется для устранения неоднозначности месяц-день в неизолированных календарных системах.
-
Temporal.PlainTime - Представляет время без даты или часового пояса; например, повторяющееся событие, которое происходит в одно и то же время каждый день. По сути, он представлен как комбинация значений часа, минуты, секунды, миллисекунды, микросекунды и наносекунды.
-
Temporal.PlainYearMonth - Представляет год и месяц календарной даты, без дня или часового пояса; например, событие в календаре, которое происходит в течение всего месяца. По сути, он представлен как календарная дата ISO 8601 с полями года, месяца и дня и связанной с ней системой календаря. День используется для устранения неоднозначности год-месяц в неизолированных календарных системах.
-
Temporal.ZonedDateTime - Представляет дату и время с часовым поясом. По сути, он представлен как комбинация мгновения (instant), часового пояса и системы календаря.
-
Temporal[Symbol.toStringTag] - Начальное значение свойства
[Symbol.toStringTag]— строка"Temporal". Это свойство используется вObject.prototype.toString().
Спецификации
| Спецификация |
|---|
| Temporal # sec-temporal-objects |
Совместимость с браузерами
| Настольные | Мобильные | Серверные | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
Temporal |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
Duration |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
Instant |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
Now |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
PlainDate |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
PlainDateTime |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
PlainMonthDay |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
PlainTime |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
PlainYearMonth |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
ZonedDateTime |
144 |
144 |
139 |
128 |
предварительная версия |
144 |
139 |
95 |
Нет |
Нет |
144 |
Нет |
1.4.0 |
2.7 |
26.0.0 |
См. также
Intl.DateTimeFormatIntl.RelativeTimeFormatIntl.DurationFormat- Полифилл Temporal от инициаторов предложения
- Полифилл Temporal от FullCalendar
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal