Дата и время
Здесь будет встроен видео-разбор темы (5–7 минут, YouTube / RuTube / VK Видео) — тем, кто лучше воспринимает на слух, текст ниже не обязателен.
Дата в JavaScript — это объект Date, внутри которого лежит одно-единственное число: миллисекунды, прошедшие с полуночи 1 января 1970 года. Год, месяц и день недели он вычисляет из этого числа на лету — и именно поэтому даты умеют вычитаться, сравниваться и сами переползать через границу месяца.
Объект даты создаётся конструктором new Date. Без аргументов он берёт текущий момент — тот, что показывают часы на машине пользователя.
С аргументами вариантов три. Строку движок разбирает по формату ISO. Отдельные числа перечисляются от крупного к мелкому: год, месяц, день, часы, минуты — и месяц здесь считается с нуля, к этому мы ещё вернёмся. Одно число — это миллисекунды от начала эпохи, поэтому new Date(0) даёт ту самую точку отсчёта.
Строка без времени читается как полночь по Гринвичу, а геттеры вроде getDate отвечают по местным часам. В Москве это всё ещё 8 марта, а в Нью-Йорке — уже 7-е, вечер. Добавьте время — и строка станет местной.
Отсюда простое правило: для хранения и передачи на сервер используйте toISOString — эта строка однозначна везде. Для показа человеку берите местное время.
Достать из даты кусочек можно только методом — свойств у Date нет. Все геттеры без приставки UTC отвечают в часовом поясе того, кто открыл страницу.
| Метод | Что возвращает | Диапазон |
|---|---|---|
| getFullYear() | год целиком | 2026 |
| getMonth() | месяц | 0–11 |
| getDate() | число месяца | 1–31 |
| getDay() | день недели | 0–6, воскресенье — 0 |
| getHours() / getMinutes() / getSeconds() | время | 0–23 / 0–59 / 0–59 |
| getTime() | миллисекунды с 1970 года | большое число |
Самая частая опечатка новичка живёт в этой таблице: getDate — это число месяца, а getDay — день недели. Имена похожи, смысл разный, ошибка тихая.
Январь — это 0, декабрь — 11. Правило действует и в конструкторе, и в getMonth, и в setMonth. А вот дни месяца нумеруются по-человечески, с единицы — то есть в одной строке кода уживаются две системы счёта.
Месяцы — с нуля, дни — с единицы. Логики нет, это наследство языка C. Просто держите в голове.
Зато нумерация с нуля отлично дружит с массивами: индекс из getMonth кладётся в массив названий без всяких - 1. Именно так обычно и делают, когда нужны свои подписи месяцев.
Метод getTime отдаёт то самое внутреннее число — таймстемп. Когда дата попадает в арифметическое выражение, движок вызывает его сам, поэтому две даты можно просто вычесть: получится разница в миллисекундах, которую остаётся поделить на длину суток.
Если нужен только таймстемп, объект создавать незачем: Date.now() сразу возвращает число. Это самый дешёвый способ замерить, сколько выполнялся кусок кода.
Операторы < и > приводят даты к числам и работают как надо. А === сравнивает объекты по ссылке: два разных объекта не равны, даже если внутри одинаковый момент времени. Приведите их к числу явно.
У каждого геттера есть парный сеттер: setDate, setMonth, setHours. И у них есть приятная особенность — выход за границы разрешён. Попросите 31 февраля, и дата спокойно переедет на март, пересчитав заодно год, если понадобится.
Тот же автоперенос работает и в конструкторе: new Date(2026, 12, 1) — это январь 2027-го. Но обратите внимание на слово «переедет»: сеттеры меняют существующий объект, а не создают новый. Если дату где-то ещё используют, изменение прилетит и туда. Поэтому функции-помощники начинают с копии.
Печатать дату вручную не нужно: браузер знает форматы всех локалей. Метод toLocaleDateString принимает код языка и объект настроек — какие части показывать и насколько подробно.
Если форматировать нужно много дат подряд, создайте форматтер один раз через Intl.DateTimeFormat и вызывайте у него format. Разбор настроек — операция небыстрая, а так она случится однажды.
Встроенного Date хватает, пока задачи простые: показать, сравнить, прибавить день. Дальше начинается больно — разбор произвольных строк, «через два месяца» с учётом разной длины месяцев, работа в чужом часовом поясе, склонения вида «3 дня назад». Тут берут библиотеку: date-fns или dayjs. Причина не в моде: Date изменяем, разбирает строки по-разному в разных браузерах и не умеет часовые пояса, кроме местного и UTC. В самом языке эти дыры чинит новый объект Temporal — он уже появляется в браузерах, но пока не везде. Что из этого брать сегодня и во что обходится каждый вариант — на полке браузера в части II.
new Dateбез аргументов даёт текущий момент, со строкой — разобранную дату ISO, с числами — год, месяц (с нуля), день, время, с одним числом — миллисекунды от 1970 года.- Месяцы нумеруются с 0 до 11, а дни месяца — с 1. Ещё легко перепутать
getDate(число месяца) иgetDay(день недели). - Внутри даты лежит число, поэтому даты можно вычитать и сравнивать через
<и>; для равенства приводите к числу —===сравнивает объекты по ссылке. - Сеттеры вроде
setDateменяют объект на месте и сами переносят дату через границу месяца и года — для чистых функций сначала делайте копию черезnew Date(date). - Показывать дату человеку удобнее через
toLocaleDateStringиIntl.DateTimeFormat; для часовых поясов, разбора строк и сложной арифметики берут библиотеку или будущийTemporal.
1/3Что выведет console.log(new Date(2026, 5, 1).getMonth())?
2/3Как получить количество дней между датами d1 и d2?
3/3В переменной d лежит 26 февраля 2026 года. Что сделает d.setDate(d.getDate() + 5)?
Сколько дней в месяце
Напишите функцию daysInMonth(year, month), которая возвращает число дней в месяце. Месяц передаётся как в Date — с нуля. Условие про високосные годы вспоминать не нужно: их знает сам объект Date.
Ключ — автоперенос дат. Нулевой день месяца не существует, поэтому Date трактует его как последний день предыдущего месяца. Берём следующий месяц и просим у него день номер ноль.
Високосность считать не пришлось: за неё отвечает сам календарь внутри Date. Кстати, при month = 11 выражение даёт month + 1 = 12 — и это тоже сработает, конструктор просто перейдёт в январь следующего года.
День недели по-русски
Напишите функцию weekDayRu(date), которая возвращает название дня недели строчными буквами. Помните, что getDay начинает неделю с воскресенья.
Самый прямой путь — массив, в котором воскресенье стоит первым, потому что getDay возвращает для него 0.
Второй вариант — переложить работу на браузер, тогда названия достанутся бесплатно для любого языка:
Массив удобен, когда нужны свои сокращения вроде «пн» и «вт»; toLocaleDateString — когда важна поддержка нескольких языков.