
Независимо от вашего мнения о JavaScript, все думают, что обработка дат – это беспорядок. Реализация объекта Date () была скопирована непосредственно из Java в 1995 году. Java отказалась от нее через два года, но осталась в JavaScript для обратной совместимости. Но скоро в стандарте появиться Temporal API
Вот проблемы, с которыми мы сталкиваемся при использовании Date ():
- он поддерживает только UTC и местное время пользователя (local time)
- нет поддержки не-григорианских календарей
- переход на летнее время непредсказуем
- анализ дат из строк ненадежен
- API неуклюжий
- объекты Date мутабельны
Самой популярной альтернативой была библиотека дат moment.js. Однако он была переведена в режим обслуживания и не должна использоваться в новых проектах. Они рекомендуют несколько альтернатив, но у каждой из них есть свои плюсы и минусы.
Объект Date() нельзя удалить из JavaScript, но новая опция Temporal находится на этапе 2 в процессе утверждения стандартов TC39. Обсуждаемые здесь свойства и методы могут быть изменены, но API должен появиться в браузерах и средах выполнения где-то в 2021 году.
Temporal Time
Temporal – это статический глобальный объект верхнего уровня (например как, Math).
Его основные цели:
- предсказуемое поведение между браузерами и средой выполнения
- более простые API для вычисления даты и времени
- поддержка не григорианских календарей
- поддержка всех часовых поясов, включая арифметику перехода на летнее время
- парсинг строк согласно спецификации ISO-8601
- сделать все объекты неизменными
API является всеобъемлющим и может измениться, но вы можете рассчитывать на ключевые функции в ближайшем будущем.
Current Date и Time
// exact time since the Unix epoch on 1 Janary, 1970 UTC Temporal.now.instant(); Temporal.now.instant().epochSeconds; Temporal.now.instant().epochMilliseconds; // current time zone Temporal.now.timeZone(); // time in current location, e.g. // 2021-09-18T04:17:48.435068431-04:00[America/New_York] Temporal.now.zonedDateTimeISO(); // time in another time zone, e.g. // 2021-09-18T09:17:48.438068435+01:00[Europe/London] Temporal.now.zonedDateTimeISO('Europe/London');
Создание инстанса Date/Times
Объект Temporal.Instant представляет отдельный момент времени с точностью до ближайшей наносекунды. Он может быть создан из строк в формате ISO 8601 или из числа секунд, миллисекунд или микросекунд:
const t1 = Temporal.Instant.from('2021-03-30T01:45:00+01:00[Europe/Berlin]'), t2 = Temporal.Instant.from('2021-04-01T02:00+01:00'), t3 = Temporal.Instant.fromEpochSeconds(1.0e8), t4 = Temporal.Instant.fromEpochMilliseconds(1.0e10), t5 = Temporal.Instant.epochNanoseconds(1.0e12);
Создание даты / времени с учетом зоны
Объект Temporal.ZonedDateTime представляет дату / время с учетом часового пояса и календаря в тот момент, когда это произошло (или произойдет) в конкретном регионе. Могут использоваться самые разные конструкторы:
new Temporal.ZonedDateTime( 1234567890000, // epoch nanoseconds Temporal.TimeZone.from('America/Los_Angeles'), // timezone Temporal.Calendar.from('iso8601') // default calendar ); Temporal.ZonedDateTime.from('2025-12-07T03:24:30+02:00[Africa/Cairo]'); Temporal.Instant('2022-08-05T20:06:13+05:45').toZonedDateTime('+05:45'); Temporal.ZonedDateTime.from({ timeZone: 'America/New_York' year: 2025, month: 1, day: 7, hour: 9, minute: 30, second: 1, millisecond: 2, microsecond: 3, nanosecond: 4 });
Создание простых дат и времени
Не всегда обязательно использовать точные даты, поэтому Temporal API предоставляет объекты, не зависящие от часовых поясов. Их можно использовать для более простых событий, таких как встреча в 14:00 сегодня.
Temporal.PlainDateTime относится к календарной дате и времени
Temporal.PlainDate относится к определенной календарной дате
Temporal.PlainTime относится к определенному времени суток.
Temporal.PlainYearMonth относится к дате без компонента дня, например «апрельская встреча 2021 года».
Temporal.PlainMonthDay относится к дате без компонента года, например, «день числа Пи – 14 марта».
У всех похожие конструкторы:
// create a new PlainDateTime // both are 4 May 2021 at 1:14pm and 15 seconds new Temporal.PlainDateTime(2021, 5, 4, 13, 14, 15); Temporal.PlainDateTime.from('2021-05-04T13:14:15'); // create a new PlainDate // both are 4 May, 2021 new Temporal.PlainDate(2021, 5, 4); Temporal.PlainDate.from('2021-05-04'); // create a new PlainTime // both are 1:14pm and 15 seconds new Temporal.PlainTime(13, 14, 15); Temporal.PlainTime.from('13:14:15'); // create a new year PlainYearMonth // both are April 2021 new Temporal.PlainYearMonth(2021, 4); Temporal.PlainYearMonth.from('2019-04'); // create a new PlainMonthDay // both are 14 March new Temporal.PlainMonthDay(3, 14); Temporal.PlainMonthDay.from('03-14');
Получение значений
Все объекты Temporal могут возвращать дискретные значения относительно определенной даты / времени. Например, используя ZonedDateTime:
const t1 = Temporal.ZonedDateTime.from('2025-12-07T03:24:30+02:00[Africa/Cairo]'); t1.year; // 2025 t1.month; // 12 t1.day; // 7 t1.hour; // 3 t1.minute; // 24 t1.second; // 30 t1.millisecond; // 0 t1.microsecond; // 0 t1.nanosecond; // 0
Другие полезные свойства:
dayOfWeek (от 1 для Понедельника до 7 для Воскресенья) dayOfYear (от 1 до 365 или 366) weekOfYear ( от 1 до 52, или иногда 53) daysInMonth (28, 29, 30, или 31) daysInYear (365 или 366) inLeapYear (true или false)
Сравнение и сортировка дат
Все объекты Temporal можно сравнить с помощью функции compare(), которая возвращает целое число. Например, чтобы сравнить два объекта ZonedDateTime:
// returns: // -1 if t1 is before t2 // 0 if t1 and t2 are the same // 1 is t1 is after t2 Temporal.ZonedDateTime.compare(t1, t2);
compare() можно использовать как функцию при сортировке массива sort() для упорядочивания даты и времени в возрастающем хронологическом порядке (от раннего к последнему):
const t = [ '2022-01-01T00:00:00+00:00[Europe/London]', '2022-01-01T00:00:00+00:00[Africa/Cairo]', '2022-01-01T00:00:00+00:00[America/New_York]' ].map( d => Temporal.ZonedDateTime.from(d) ) .sort( Temporal.ZonedDateTime.compare );
Расчет даты
Предусмотрено несколько методов для вычисления даты для любого объекта Temporal. Все они возвращают новый Temporal того же типа при передаче объекта Temporal.Duration, который определяет период в годах, месяцах, днях, часах и т. Д.
const t1 = Temporal.ZonedDateTime.from('2022-01-01T00:00:00+00:00[Europe/London]'); // add 8 hours 30 minutes t1.add({ hours: 8, minutes: 30 }); // subtract 5 days t1.subtract({ days: 5 }); // round to nearest month t1.round({ smallestUnit: 'month' });
Обратите внимание, что Plain даты и время могут переноситься. Например, добавление 24 часов к любому PlainTime вернет объект, содержащий идентичное значение.
Методы until() и since() возвращают объект Temporal.Duration, описывающий время до или после определенной даты / времени:
// mounths until t1 t1.until().months; // weeks since t1 t1.since().weeks;
Наконец, метод equals() может определить, эквивалентны ли два значения даты / времени:
const d1 = Temporal.PlainDate.from('2022-01-31'); d2 = Temporal.PlainDate.from('2021-01-31'); d1.equals(d2); // false
Форматирование дат с помощью API интернационализации
Не являясь частью Temporal API, JavaScript Intl (Internationalization) API предоставляет конструктор DateTimeFormat(), который можно использовать для форматирования объектов Temporal или Date:
const d = new Temporal.PlainDate(2021, 3, 14); // 3/14/2021 new Intl.DateTimeFormat('en-US').format(d); // 14/3/2021 new Intl.DateTimeFormat('en-GB').format(d); // miércoles, 14 de abril de 2021 new Intl.DateTimeFormat('es-ES', { dateStyle: 'full' }).format(d);
Temporal API. Когда начинать использовать?
Объект Date() был причиной разочарования разработчиков четверть века. Хотя нет никаких гарантий, что Temporal быстро станет стандартной функцией, будущее дат JavaScript выглядит немного лучше.
Вы можете попробовать Temporal сегодня с помощью экспериментального полифилла, но не используйте его в продакшене (пока)!
Дальнейшая информация:
- Temporal документация
- Temporal Cookbook – примеры использования