Русский

Подробное руководство по JavaScript Temporal API, современному решению для эффективной обработки дат и времени в различных международных контекстах.

JavaScript Temporal API: Современная обработка даты и времени для глобальной аудитории

Объект `Date` в JavaScript долгое время был источником разочарования для разработчиков. Его изменяемость, непоследовательный API и слабая поддержка часовых поясов привели к появлению многочисленных библиотек, таких как Moment.js и date-fns, для восполнения пробелов. Теперь, с появлением Temporal API, JavaScript предлагает современное встроенное решение для работы с датами и временем с улучшенной ясностью и точностью. В этой статье представлен всесторонний обзор Temporal API с акцентом на его возможностях, преимуществах и использовании в различных международных контекстах.

Что такое Temporal API?

Temporal API — это новый глобальный объект в JavaScript, разработанный для устранения недостатков объекта `Date`. Он предоставляет чистый, неизменяемый API для работы с датами, временем, часовыми поясами и календарными системами. Что особенно важно, он стремится представлять концепции даты и времени таким образом, чтобы они более точно соответствовали реальному использованию и ожиданиям, что значительно упрощает интернационализацию.

Ключевые особенности:

Основные объекты Temporal

Temporal API вводит несколько новых типов объектов. Вот некоторые из основных:

Работа с датами

Создание `Temporal.PlainDate`

Чтобы создать `Temporal.PlainDate`, вы можете использовать конструктор:

const plainDate = new Temporal.PlainDate(2024, 10, 27); // Год, Месяц (1-12), День
console.log(plainDate.toString()); // Вывод: 2024-10-27

Вы также можете использовать метод `from`, который принимает строку в формате ISO 8601:

const plainDateFromString = Temporal.PlainDate.from('2024-10-27');
console.log(plainDateFromString.toString()); // Вывод: 2024-10-27

Получение компонентов даты

Вы можете получить доступ к отдельным компонентам даты, используя свойства, такие как `year`, `month` и `day`:

console.log(plainDate.year); // Вывод: 2024
console.log(plainDate.month); // Вывод: 10
console.log(plainDate.day); // Вывод: 27

Арифметические операции с датами

Для добавления или вычитания дней, недель, месяцев или лет используйте методы `plus` и `minus`. Эти методы возвращают новый объект `Temporal.PlainDate`:

const nextWeek = plainDate.plus({ days: 7 });
console.log(nextWeek.toString()); // Вывод: 2024-11-03

const lastMonth = plainDate.minus({ months: 1 });
console.log(lastMonth.toString()); // Вывод: 2024-09-27

Сравнение дат

Вы можете сравнивать даты с помощью метода `compare`:

const date1 = new Temporal.PlainDate(2024, 10, 27);
const date2 = new Temporal.PlainDate(2024, 11, 15);

console.log(Temporal.PlainDate.compare(date1, date2)); // Вывод: -1 (date1 раньше, чем date2)

Работа со временем

Создание `Temporal.PlainTime`

Чтобы создать `Temporal.PlainTime`, используйте конструктор:

const plainTime = new Temporal.PlainTime(10, 30, 0); // Час, Минута, Секунда
console.log(plainTime.toString()); // Вывод: 10:30:00

Или используйте метод `from` со строкой времени в формате ISO 8601:

const plainTimeFromString = Temporal.PlainTime.from('10:30:00');
console.log(plainTimeFromString.toString()); // Вывод: 10:30:00

Получение компонентов времени

console.log(plainTime.hour); // Вывод: 10
console.log(plainTime.minute); // Вывод: 30
console.log(plainTime.second); // Вывод: 0

Арифметические операции со временем

const later = plainTime.plus({ minutes: 15 });
console.log(later.toString()); // Вывод: 10:45:00

Совместная работа с датой и временем

Создание `Temporal.PlainDateTime`

Вы можете создать `Temporal.PlainDateTime` напрямую или объединив `Temporal.PlainDate` и `Temporal.PlainTime`:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
console.log(plainDateTime.toString()); // Вывод: 2024-10-27T10:30:00

const date = new Temporal.PlainDate(2024, 10, 27);
const time = new Temporal.PlainTime(10, 30, 0);
const combinedDateTime = date.toPlainDateTime(time);
console.log(combinedDateTime.toString()); // Вывод: 2024-10-27T10:30:00

Часовые пояса

Правильная обработка часовых поясов имеет решающее значение для приложений, работающих с пользователями в разных местах. Temporal API обеспечивает надежную поддержку часовых поясов через объекты `Temporal.ZonedDateTime` и `Temporal.TimeZone`.

Создание `Temporal.ZonedDateTime`

Для создания `Temporal.ZonedDateTime` вам понадобится `Temporal.PlainDateTime` и идентификатор часового пояса. Идентификаторы часовых поясов основаны на базе данных часовых поясов IANA (например, `America/Los_Angeles`, `Europe/London`, `Asia/Tokyo`).

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
console.log(zonedDateTime.toString()); // Вывод: 2024-10-27T10:30:00-07:00[America/Los_Angeles] (смещение будет зависеть от правил летнего времени)

В качестве альтернативы можно создать `Temporal.ZonedDateTime` из `Instant`.

const instant = Temporal.Instant.fromEpochSeconds(1666866600); // Пример временной метки
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO(timeZone); // Часовой пояс, например 'America/Los_Angeles'
console.log(zonedDateTimeFromInstant.toString());

Преобразование между часовыми поясами

Вы можете преобразовать `Temporal.ZonedDateTime` в другой часовой пояс с помощью метода `withTimeZone`:

const newTimeZone = 'Europe/London';
const zonedDateTimeInLondon = zonedDateTime.withTimeZone(newTimeZone);
console.log(zonedDateTimeInLondon.toString()); // Вывод: 2024-10-27T18:30:00+01:00[Europe/London]

Работа со смещениями часовых поясов

Метод `getOffsetStringFor` объекта `Temporal.TimeZone` предоставляет строку смещения для заданного `Temporal.Instant`:

const timeZoneObject = new Temporal.TimeZone(timeZone);
const offsetString = timeZoneObject.getOffsetStringFor(zonedDateTime.toInstant());
console.log(offsetString); // Вывод: -07:00 (в зависимости от правил летнего времени)

Для точных расчетов необходимо использовать правильные идентификаторы часовых поясов IANA. Эти идентификаторы поддерживаются и регулярно обновляются, чтобы отражать изменения в летнем времени и границах часовых поясов.

Длительности (Durations)

Объект `Temporal.Duration` представляет собой промежуток времени. Его можно использовать для добавления или вычитания из дат и времени.

Создание `Temporal.Duration`

Вы можете создать `Temporal.Duration` с помощью конструктора, указав годы, месяцы, дни, часы, минуты, секунды, миллисекунды, микросекунды и наносекунды:

const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9); // Годы, Месяцы, Дни, Часы, Минуты, Секунды, Миллисекунды, Микросекунды, Наносекунды
console.log(duration.toString()); // Вывод: P1Y2M3DT4H5M6.007008009S

Или используя строку длительности в формате ISO 8601:

const durationFromString = Temporal.Duration.from('P1Y2M3DT4H5M6S');
console.log(durationFromString.toString()); // Вывод: P1Y2M3DT4H5M6S

Добавление длительностей к датам и времени

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const duration = new Temporal.Duration(0, 0, 7); // 7 дней
const newDate = plainDate.plus(duration);
console.log(newDate.toString()); // Вывод: 2024-11-03

Обратите внимание, что добавление длительностей, включающих месяцы или годы, к датам требует осторожного подхода, так как количество дней в месяце или году может варьироваться.

Календарные системы

Temporal API поддерживает различные календарные системы помимо григорианского календаря. Это крайне важно для приложений, которым необходимо обрабатывать даты в различных культурных контекстах. Хотя поддержка все еще развивается, она обеспечивает основу для будущего расширения.

Использование альтернативных календарей

Чтобы использовать определенный календарь, вы можете указать его при создании объектов Temporal:

const hebrewDate = new Temporal.PlainDate(5785, 1, 1, { calendar: 'hebrew' });
console.log(hebrewDate.toString()); // Конкретный вывод может варьироваться в зависимости от реализации и форматирования. На момент написания статьи во многих средах требуется полифил.

Важно: Поддержка негригорианских календарей может потребовать полифилов или специальной поддержки браузера/среды. Проверяйте документацию Temporal API и таблицы совместимости браузеров для получения последней информации.

Форматирование дат и времени

Хотя Temporal API фокусируется на манипулировании датой и временем, форматирование обычно выполняется с помощью объекта `Intl.DateTimeFormat`, который является частью Internationalization API. Объекты Temporal без проблем работают с `Intl.DateTimeFormat`.

Использование `Intl.DateTimeFormat`

Вот как отформатировать `Temporal.PlainDate` с помощью `Intl.DateTimeFormat`:

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatter.format(plainDate)); // Вывод: October 27, 2024

const formatterGerman = new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatterGerman.format(plainDate)); // Вывод: 27. Oktober 2024

Вы можете настраивать параметры формата в соответствии с вашими потребностями. Первый аргумент `Intl.DateTimeFormat` — это локаль, которая определяет язык и региональные соглашения, используемые для форматирования. Использование разных локалей (например, 'en-US', 'de-DE', 'fr-FR', 'ja-JP') приводит к разным форматам вывода.

Форматирование `Temporal.ZonedDateTime`

Форматирование `Temporal.ZonedDateTime` происходит аналогично, но вы также можете включить в вывод информацию о часовом поясе:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);

const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'short' });
console.log(formatter.format(zonedDateTime)); // Вывод: October 27, 2024, 10:30 AM PDT (аббревиатура часового пояса зависит от правил летнего времени)

Лучшие практики интернационализации

При работе с датами и временем в глобальном контексте учитывайте следующие лучшие практики:

Сравнение Temporal API с устаревшим объектом Date

Вот таблица, подчеркивающая ключевые различия и преимущества Temporal API по сравнению с устаревшим объектом `Date`:

Характеристика Устаревший объект `Date` Temporal API
Изменяемость Изменяемый (модифицирует исходный объект) Неизменяемый (возвращает новые объекты)
Поддержка часовых поясов Ограниченная и часто проблематичная Надежная и точная, основана на базе данных часовых поясов IANA
API Непоследовательный и сложный в использовании Понятный, последовательный и интуитивный
Точность Миллисекундная Наносекундная
Календарные системы Ограничена григорианским календарем Поддерживает альтернативные календарные системы (с развивающейся поддержкой)
Интернационализация Требует внешних библиотек для надежной интернационализации Встроенная поддержка и бесшовная интеграция с `Intl.DateTimeFormat`

Поддержка браузерами и полифилы

Поскольку Temporal API является относительно новым, его поддержка браузерами все еще развивается. Проверяйте последние таблицы совместимости браузеров (например, на MDN Web Docs), чтобы узнать, какие браузеры и среды поддерживают его нативно. Для старых браузеров или сред без нативной поддержки вы можете использовать полифилы для предоставления функциональности Temporal API. Найдите в интернете «Temporal API polyfill», чтобы найти подходящие варианты.

Заключение

JavaScript Temporal API представляет собой значительный шаг вперед в обработке дат и времени в JavaScript. Его неизменяемость, понятный API, надежная поддержка часовых поясов и возможности календарных систем делают его мощным инструментом для разработчиков, создающих приложения, которым необходимо точно и надежно работать с датами и временем в различных международных контекстах. Хотя поддержка браузерами все еще развивается, преимущества Temporal API делают его достойным изучения и внедрения в новые проекты. Применяя Temporal API и следуя лучшим практикам интернационализации, вы можете создавать приложения, которые обеспечивают безупречный и точный опыт работы с датой и временем для пользователей по всему миру.

Для дальнейшего изучения