Если вы когда-нибудь пытались вычесть одну дату из другой или просто вывести текущий месяц, вы знаете, что JavaScript может вести себя как капризный ребёнок. Но не переживайте — за 10 лет разработки я собрал все грабли, чтобы вы по ним не ходили. В этой статье мы разберём, как работать с датами и временем без боли и лишних библиотек.
Знакомьтесь, объект Date
В JavaScript нет отдельного типа данных для дат. Вместо этого есть объект Date, который хранит количество миллисекунд, прошедших с 1 января 1970 года (эпоха Unix). Да, именно с этой даты началась вся цифровая эра. Если вам кажется, что это странно — просто запомните, что все даты внутри — это числа.
Создать дату можно несколькими способами:
// Текущий момент
const now = new Date();
// По строке (лучше использовать ISO-формат)
const specificDate = new Date('2025-06-15T12:00:00');
// По компонентам (месяцы с 0 до 11!)
const birthday = new Date(2025, 5, 15); // 15 июня 2025
// По миллисекундам
const fromEpoch = new Date(0); // Thu Jan 01 1970
Обратите внимание на важный момент: месяцы в JavaScript начинаются с нуля. Январь — это 0, февраль — 1 и так далее. Это частая причина багов, когда вы показываете пользователю месяц, а он на единицу меньше ожидаемого.
Основные методы: что и как получать
У объекта Date есть куча методов для получения разных частей даты. Вот самые полезные:
| Метод | Что возвращает | Пример значения |
|---|---|---|
getFullYear() |
Год (4 цифры) | 2025 |
getMonth() |
Месяц (0-11) | 5 (июнь) |
getDate() |
День месяца (1-31) | 15 |
getDay() |
День недели (0-6, воскресенье = 0) | 3 (среда) |
getHours() |
Часы (0-23) | 14 |
getMinutes() |
Минуты (0-59) | 30 |
getSeconds() |
Секунды (0-59) | 45 |
Также есть методы для установки значений, например setFullYear(), setMonth() и так далее. Они меняют дату на месте и возвращают количество миллисекунд новой даты.
Обратите внимание: методы getDay() и getDate() легко перепутать. getDay() — это день недели, а getDate() — число месяца. Я сам путался первые пару лет.
Форматирование: как вывести дату красиво
Когда вы пытаетесь показать дату пользователю, просто вызвав toString(), вы получите что-то вроде "Wed Jun 15 2025 14:30:45 GMT+0300 (Москва, стандартное время)". Это не очень дружелюбно, согласитесь.
В современном JavaScript есть отличный метод toLocaleString(), который учитывает региональные настройки:
const date = new Date(2025, 5, 15, 14, 30);
// Русская локаль
console.log(date.toLocaleString('ru-RU')); // 15.06.2025, 14:30:00
// Только дата
console.log(date.toLocaleDateString('ru-RU')); // 15.06.2025
// Только время
console.log(date.toLocaleTimeString('ru-RU')); // 14:30:00
Можно даже настроить формат под свои нужды:
const options = {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
};
console.log(date.toLocaleDateString('ru-RU', options));
// воскресенье, 15 июня 2025 г.
Если вам нужен полностью свой формат, придётся собирать строку вручную. Например, чтобы получить "2025-06-15", можно сделать так:
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
Метод padStart() здесь добавляет ноль в начало, если число меньше 10. Это простой лайфхак, который избавляет от кучи лишних проверок.
toString(). Всегда используйте toLocaleString() или собирайте строку вручную. Это убережёт вас от сюрпризов с часовыми поясами и форматами.
Сравнение и вычисление разницы между датами
Так как даты хранятся как числа (миллисекунды), вы можете сравнивать их напрямую с помощью операторов <, >, <= и так далее. Но будьте осторожны: оператор == не работает корректно, потому что сравниваются ссылки на объекты, а не значения. Используйте getTime() для сравнения:
const date1 = new Date(2025, 5, 15);
const date2 = new Date(2025, 5, 15);
console.log(date1 == date2); // false (разные объекты)
console.log(date1.getTime() == date2.getTime()); // true
Для вычисления разницы просто вычтите одну дату из другой. Результат будет в миллисекундах. Чтобы перевести в дни, разделите на количество миллисекунд в сутках:
const start = new Date(2025, 5, 1);
const end = new Date(2025, 5, 15);
const diffMs = end - start; // разница в миллисекундах
const diffDays = diffMs / (1000 * 60 * 60 * 24);
console.log(diffDays); // 14
Это работает, но есть подводный камень: если между датами есть переход на летнее время (в странах, где оно есть), то в сутках может быть 23 или 25 часов. Чтобы избежать ошибок, лучше нормализовать даты до UTC:
function daysBetween(date1, date2) {
const msPerDay = 1000 * 60 * 60 * 24;
// Убираем время, оставляем только дату в UTC
const utc1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate());
const utc2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate());
return Math.floor((utc2 - utc1) / msPerDay);
}
Подводные камни и советы
Самый большой источник головной боли — часовые пояса. Когда вы создаёте дату из строки, JavaScript интерпретирует её в местном часовом поясе браузера или сервера. Если вы передаёте дату между клиентом и сервером, лучше использовать UTC или ISO-строку с указанием часового пояса.
Например, new Date('2025-06-15') создаст дату в UTC (потому что строка без времени интерпретируется как полночь по UTC), а new Date(2025, 5, 15) — в местном времени. Это приводит к неожиданным сдвигам на день при выводе в другом часовом поясе.
Чтобы получить текущее время в UTC, используйте методы getUTCFullYear(), getUTCMonth() и так далее. А для отправки на сервер — toISOString():
const now = new Date();
console.log(now.toISOString()); // 2025-06-15T11:30:00.000Z
Буква Z на конце означает UTC.
Ещё один момент: не пытайтесь вручную добавлять дни, умножая 24 часа на количество дней. Лучше использовать setDate():
const date = new Date(2025, 5, 15);
date.setDate(date.getDate() + 30); // добавляем 30 дней
console.log(date.toDateString()); // правильно учтёт переход через месяц
Этот метод автоматически корректирует месяц и год, если нужно.
date-fns или встроенного объекта Intl.DateTimeFormat. Но для простых задач хватит и стандартного Date — главное, знать его особенности.
Современные альтернативы: Temporal
В JavaScript на подходе новый API для работы с датами — Temporal. Он уже доступен в некоторых средах как экспериментальный. Temporal решает многие проблемы Date: неизменяемость, поддержка часовых поясов, более удобные методы.
Вот как выглядит создание даты с Temporal:
// Пока не стандарт, но уже можно попробовать
const date = Temporal.PlainDate.from('2025-06-15');
console.log(date.toString()); // 2025-06-15
Но пока Temporal не полностью поддержан во всех браузерах, лучше использовать проверенные решения.
Итоговое резюме
Работа с датами в JavaScript — это не ракетостроение, но требует внимательности. Запомните главное:
- Месяцы считаются с нуля, поэтому всегда добавляйте 1 при выводе.
- Для сравнения дат используйте
getTime(), а не==. - Для вычисления разницы переводите даты в UTC, чтобы избежать проблем с часовыми поясами.
- Используйте
setDate()для добавления дней, а не ручные вычисления. - Для форматирования используйте
toLocaleString()с нужной локалью.
Теперь вы знаете основные подводные камни и можете смело писать код, который будет правильно работать с датами. Практикуйтесь, и вскоре даты станут для вас обычным делом.
Удачи в кодинге!



