Время в JavaScript: практическое руководство

Раздел: Основы JavaScript -> Дата и время

Основы работы с датой и временем в JavaScript

Основным инструментом для работы с датами и временем является встроенный объект Date. Он хранит момент времени в виде количества миллисекунд, прошедших с 1 января 1970 года 00:00:00 UTC (эпоха Unix). Для создания экземпляра даты используется конструктор new Date().

const now = new Date();
console.log(now); // Текущая дата и время в локальном часовом поясе

Js date (дата в javascript)

Пояснение: Конструктор без аргументов возвращает текущий момент. Если передать один числовой аргумент, он интерпретируется как количество миллисекунд. Строковый аргумент разбирается по правилам парсинга. Основные методы для чтения компонентов: getFullYear(), getMonth() (0-11), getDate(), getHours(), getMinutes(), getSeconds(). Метод getTime() возвращает количество миллисекунд с эпохи.

Типичная ошибка: Метод getMonth() возвращает значения от 0 (январь) до 11 (декабрь). При отображении или вычислениях без коррекции получается месяц на единицу меньше.

Решение: Всегда прибавлять 1: now.getMonth() + 1. Для установки месяца используется setMonth(month), где month - число от 0 до 11.

Как преобразовать строку в дату и обработать некорректный формат?

Для разбора строк применяется Date.parse() или конструктор new Date(dateString). Надёжнее всего использовать формат ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ).

const date1 = new Date("2023-12-25");
console.log(date1); // Mon Dec 25 2023 03:00:00 GMT+0300 (MSK)
const date2 = new Date("2023-12-25T10:30:00");
console.log(date2); // Время с учётом часового пояса

Js время (работа с временем в javascript)

Пояснение: Парсинг строк вида "12/25/2023" зависит от локали браузера и может привести к неожиданной интерпретации (месяц/день путаются). Date.parse() возвращает число миллисекунд или NaN при ошибке.

Проблема: Разные браузеры и версии могут по-разному разбирать нестандартные строки. Например, "2023/12/25" может быть воспринят как локальное время или UTC.

Решение: Использовать только строки в формате ISO 8601. Для разбора произвольных форматов рекомендуется писать собственный парсер или применять библиотеки (moment.js, date-fns), которые предоставляют явное указание формата.

Как вычислить разницу между двумя датами в днях с учётом перехода на летнее время?

Разность двух объектов Date даёт количество миллисекунд. Деление на количество миллисекунд в сутках (86400000) часто приводит к дробному результату из-за DST. Для получения целого числа дней используют округление или работу в UTC.

const start = new Date("2024-03-30");
const end = new Date("2024-04-02");
const diffMs = end - start;
const diffDays = diffMs / (1000 * 60 * 60 * 24);
console.log(diffDays); // 3.0416666666666665 (из-за перевода часов)

Js год года лет (склонение дат (год/года/лет) в javascript)

Для точного подсчёта полных дней можно обнулить время и использовать UTC-методы:

const startUTC = Date.UTC(2024, 2, 30); // март (индекс 2)
const endUTC = Date.UTC(2024, 3, 2);   // апрель
const diffDays = (endUTC - startUTC) / 86400000;
console.log(diffDays); // 3

Пояснение: Date.UTC() возвращает миллисекунды в UTC, что исключает влияние часового пояса и DST.

Ошибка: Если использовать простой подход с вычитанием локальных дат, дни могут быть нецелыми (например, 6.9583). Это приведёт к ложным результатам при подсчёте возраста или количества дней между событиями.

Решение: Применять Math.round() для округления или переводить обе даты в UTC перед вычислениями.

Как отформатировать дату с учётом региональных стандартов?

Для локализованного форматирования применяется объект Intl.DateTimeFormat. Он позволяет выводить дату в формате, привычном для пользователя.

const date = new Date(2024, 0, 15, 14, 30); // 15 января 2024 14:30
const formatter = new Intl.DateTimeFormat("ru-RU", {
    year: "numeric",
    month: "long",
    day: "numeric",
    hour: "2-digit",
    minute: "2-digit"
});
console.log(formatter.format(date)); // "15 января 2024 г., 14:30"

Пояснение: Первый параметр - локаль ("ru-RU", "en-US", "de-DE" и т.д.). Второй параметр - объект опций, где можно указать, какие компоненты отображать и в каком виде (numeric, long, short, 2-digit).

Проблема: В старых браузерах (например, Internet Explorer) Intl.DateTimeFormat может не поддерживать некоторые опции, и результат может отличаться.

Решение: Для критичных приложений можно использовать полифил или написать функцию форматирования вручную, собирая строку из компонентов через getFullYear(), getMonth() и т.д.

Как получить Unix-штамп (количество секунд с 1970 года)?

Объект Date предоставляет метод getTime(), возвращающий миллисекунды. Для перевода в секунды достаточно разделить на 1000.

const now = new Date();
const unixMs = now.getTime();
const unixSec = Math.floor(now.getTime() / 1000);
console.log("Миллисекунды:", unixMs);
console.log("Секунды:", unixSec);

Обратное преобразование: передача количества миллисекунд в конструктор.

const fromMs = new Date(1704067200000);  // 2024-01-01 00:00:00 UTC
console.log(fromMs);

Пояснение: Unix-время используется для передачи дат между сервером и клиентом, для хранения в базах данных, а также для вычислений, не зависящих от часового пояса.

Ошибка: Путаница между секундами и миллисекундами. Если передать в конструктор Date значение в секундах, дата будет интерпретирована как миллисекунды, что даст дату через 1970 год на указанное количество секунд (неверно).

Решение: Всегда умножать секунды на 1000 при создании Date из Unix-штампа: new Date(unixSeconds * 1000).

Дополнительные примеры работы с временем

Определение количества дней в заданном месяце

Полезная задача - получить число дней в конкретном месяце с учётом високосности. Используется трюк: установить дату на следующий месяц и обнулить день.

Пример
function getDaysInMonth(year, month) {
    // month от 0 до 11
    return new Date(year, month + 1, 0).getDate();
}

console.log(getDaysInMonth(2024, 1)); // 29 (февраль 2024 високосный)
console.log(getDaysInMonth(2023, 1)); // 28 (февраль 2023)
29
28

Пояснение: new Date(year, month+1, 0) создаёт дату с месяцем, увеличенным на 1, и днём 0. Это означает последний день предыдущего месяца. Метод getDate() возвращает число этого дня.

Вычисление возраста на текущую дату

При расчёте возраста нужно учитывать, был ли уже день рождения в текущем году.

Пример
function calculateAge(birthdate) {
    const today = new Date();
    const birth = new Date(birthdate);
    let age = today.getFullYear() - birth.getFullYear();
    const monthDiff = today.getMonth() - birth.getMonth();
    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
        age--;
    }
    return age;
}

const born = "1990-05-20";
console.log("Возраст:", calculateAge(born));
Возраст: 34 (на момент 2025-03-01)

Пояснение: Сначала вычисляется разница в годах. Затем, если текущий месяц меньше месяца рождения, или месяц совпадает, но день ещё не наступил, возраст уменьшается на 1. Это стандартный подход.

Создание массива дат между двумя моментами (все дни)

Генерация последовательности дат полезна для календарей или аналитики.

Пример
function generateDateRange(start, end) {
    const dates = [];
    let current = new Date(start);
    const endDate = new Date(end);
    while (current <= endDate) {
        dates.push(new Date(current)); // копия
        current.setDate(current.getDate() + 1);
    }
    return dates;
}

const range = generateDateRange("2024-01-28", "2024-02-02");
console.log(range.map(d => d.toISOString().slice(0,10)));
["2024-01-28", "2024-01-29", "2024-01-30", "2024-01-31", "2024-02-01", "2024-02-02"]

Пояснение: Цикл увеличивает текущую дату на 1 день с помощью setDate(). Важно создавать копию объекта, иначе все элементы массива будут ссылаться на один и тот же изменяющийся объект.

Парсинг даты из нестандартной строки (DD.MM.YYYY)

Для формата "31.12.2023" приходится разбирать строку вручную.

Пример
function parseCustomDate(str) {
    const parts = str.split('.');
    if (parts.length !== 3) return null;
    const day = parseInt(parts[0], 10);
    const month = parseInt(parts[1], 10) - 1; // месяц в JS 0-11
    const year = parseInt(parts[2], 10);
    return new Date(year, month, day);
}

const date = parseCustomDate("31.12.2023");
console.log(date.toISOString().slice(0,10));
2023-12-31

Пояснение: Разделение по точке, преобразование к числам, коррекция месяца. Проверка корректности (например, день не должен быть больше 31) может быть добавлена для надёжности. Такой подход полностью контролируем и не зависит от браузера.

Определение дня недели для 1 января заданного года

Полезно при построении календаря.

Пример
function getFirstDayOfYear(year) {
    const firstJan = new Date(year, 0, 1);
    return firstJan.getDay(); // 0 = воскресенье, 1 = понедельник, ...
}

console.log("1 января 2025 - день недели:", getFirstDayOfYear(2025));
1 января 2025 - день недели: 3

Пояснение: getDay() возвращает номер дня недели, где воскресенье - 0, понедельник - 1, и т.д. Для получения названия дня можно использовать Intl.DateTimeFormat с опцией weekday: "long".

Работа с временем в JavaScript - comments

En
Js время (javascript)