JavaScript: Даты и время
В веб-разработке умение работать с датами и временем необходимо для создания динамичных и ориентированных на пользователя приложений. JavaScript предоставляет встроенный объект Date.
Введение в объект Date в JavaScript
Умение работать с датами и временем — обязательный навык для создания динамичных веб-приложений. JavaScript предоставляет встроенный объект Date для решения этих задач. В этом руководстве рассказывается, как создавать даты, считывать и изменять их компоненты, форматировать их и выполнять арифметические операции с датами — с запускаемыми примерами на протяжении всего текста.
Внутренне Date — это просто одно число: количество миллисекунд с начала эпохи Unix (00:00:00 UTC 1 января 1970 года). Все остальные возможности построены поверх этого одного числа, поэтому большая часть логики работы с датами сводится к обычной математике с числами.
Создание объектов Date
Существует четыре распространённых способа создать экземпляр Date — для разных входных данных.
// 1. Current date and time (no arguments)
const now = new Date();
// 2. From a millisecond timestamp (epoch = 0)
const epoch = new Date(0); // 1970-01-01T00:00:00.000Z
// 3. From a date string (ISO 8601 is the only reliably portable format)
const parsed = new Date("2024-01-01T00:00:00");
// 4. From individual components: year, monthIndex, day, hours, minutes, seconds
const detailed = new Date(2024, 0, 1, 15, 30, 0); // Jan 1, 2024, 15:30:00Месяц индексируется с нуля. В форме с компонентами январь — это 0, февраль — 1, … декабрь — 11. День месяца, напротив, нумеруется с единицы. Это смещение на единицу — самая распространённая ошибка при работе с Date. Та же индексация с нуля применяется к getMonth() и setMonth().
Разбор строк ISO против других форматов
Только формат ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) гарантированно разбирается одинаково в любом движке. Простая строка с датой вида "2024-01-01" трактуется как полночь по UTC, тогда как "2024-01-01T00:00:00" (без Z) — как локальное время. Другие форматы (например, "01/02/2024") зависят от реализации — их следует избегать.
Получение компонентов даты и времени
Получив объект Date, вы можете считать каждую его часть с помощью метода get*. Эти методы возвращают значения местного времени (варианты для UTC описаны в разделе Работа с часовыми поясами).
Изменение компонентов даты и времени
Для каждого метода get* существует соответствующий метод set*, который изменяет дату на месте. Объекты Date мутабельны — set* меняет оригинал, а не возвращает новую дату.
Автокоррекция (переполнение переходит в следующий период)
Если вы задаёте значение вне допустимого диапазона, Date тихо нормализует его — ошибки не возникает. Если установить день 32 января, дата переходит на февраль. Это действительно удобно для арифметики: чтобы прибавить 5 дней, достаточно добавить 5 к getDate() и позволить дате перейти на следующий месяц.
Метки времени: getTime и Date.now
getTime() возвращает дату в виде метки времени в миллисекундах, а статический метод Date.now() возвращает текущую метку без создания объекта. Метки времени — самый простой способ сравнить даты или измерить прошедшее время.
Работа с часовыми поясами
Объект Date хранит единый момент времени в UTC; методы get* читают его в локальном часовом поясе хоста. Используйте варианты getUTC* для получения значений по UTC, а API Intl (через toLocaleString) — для отображения в любом другом поясе.
Форматирование дат и времени
Для получения строки, пригодной для машинной обработки, используйте toISOString(); для вывода в удобочитаемом виде toLocaleDateString() / toLocaleTimeString() учитывают локаль пользователя. Для полностью произвольного формата соберите компоненты вручную (не забывая прибавлять + 1 к getMonth()).
toISOString() — это именно тот метод, который JSON.stringify использует для дат, поэтому объект Date успешно переживает преобразование в текст и обратно. Смотрите раздел Работа с JSON о том, как восстанавливать строки ISO в объекты Date.
Изучите современные библиотеки для работы с датами: несмотря на то что нативный объект Date JavaScript обеспечивает базовую работу с датами, библиотеки date-fns и Luxon предлагают расширенные инструменты для сложных вычислений, интернационализации и работы с часовыми поясами. Moment.js официально объявлен устаревшим; для новых проектов рассмотрите эти современные альтернативы.
Арифметика с датами и вычисление разниц
Поскольку Date по сути является числом, вычитание одной даты из другой даёт разность в миллисекундах. Оператор вычитания приводит каждую дату через getTime(), поэтому endDate - startDate работает напрямую. Разделите на количество миллисекунд в сутках, чтобы получить количество дней.
Для прибавления времени предпочтительнее мутировать дату с помощью set* (что корректно обрабатывает переполнение месяцев и лет), а не прибавлять необработанные миллисекунды, которые не учитывают переход на летнее время.
Использование библиотек для сложных операций
Для более сложных операций с датами и форматирования ряд библиотек может упростить эти задачи. Такие библиотеки, как date-fns и Luxon, предлагают расширенные возможности по сравнению с нативным объектом Date, облегчая разбор строк, интернационализацию и работу со сложными часовыми поясами. Кроме того, Temporal API находится в стадии разработки и в будущем должен заменить нативный объект Date более надёжным, иммутабельным и часовопоясным решением.
Заключение
Владение объектом Date в JavaScript необходимо для разработки динамичных веб-приложений, эффективно взаимодействующих с датами и временем. Создавая, считывая, изменяя и форматируя даты, разработчики могут реализовывать сложные функции, реагирующие на реальное время. Будь то планирование событий, вычисление продолжительности или отображение временных шкал — возможности, предоставляемые объектом Date в JavaScript и различными сторонними библиотеками, делают работу с датами и временем мощным инструментом в арсенале веб-разработчика.