Date.now() появился в ECMAScript 5 (2009) и с июля 2015 года поддерживается всеми современными браузерами (статус Baseline Widely available). Метод отвечает на один вопрос: сколько миллисекунд прошло от полуночи 1 января 1970 года по UTC (Unix epoch) до текущего момента. Такое число называют таймстемпом – универсальной меткой времени, которая не зависит от часового пояса и формата отображения. В прикладном коде таймстемпы встречаются повсюду: метки событий в логах и базах данных, ключи кэша, грубые замеры времени, контроль дрейфа таймеров setInterval.
Как это работает
Синтаксис предельно короткий: параметров нет, результат – число.
const ts = Date.now(); // например 1519211809934
// Unix-таймстемп в секундах
const unix = Math.floor(Date.now() / 1000);Date.now() – статический метод класса Date: он вызывается только на самом классе. Записи вида myDate.now() или new Date.now() не сработают – метода now() у экземпляров просто нет. Объект Date при вызове не создаётся вовсе, и это главное практическое преимущество: в горячих участках кода (игровые циклы, частые обработчики) Date.now() отрабатывает быстрее, чем new Date().getTime(), и не оставляет мусора сборщику памяти.
Тот же таймстемп дают ещё три записи: new Date().getTime(), new Date().valueOf() и +new Date – унарный плюс приводит объект даты к числу. Значение у всех четырёх одинаковое, различается только цена вызова.
Date.now(), new Date().getTime() и performance.now() – в чём разница
| Способ | Точка отсчёта | Монотонность | Точность | Назначение |
|---|---|---|---|---|
| Date.now() | Unix epoch, UTC | Нет – читает системные часы | 1 мс (в Firefox – 2 мс) | Таймстемпы событий, метки в логах и кэше |
| new Date().getTime() | Unix epoch, UTC | Нет | 1 мс | То же, но с созданием лишнего объекта Date |
| +new Date | Unix epoch, UTC | Нет | 1 мс | Краткая запись getTime(); читается хуже |
| performance.now() | timeOrigin – старт страницы или воркера | Да – значение никогда не уменьшается | Дробные мс (5–100 мкс после огрубления) | Замеры длительности, профилирование |
Ключевое отличие performance.now() – монотонные часы. Date.now() привязан к системному времени: если операционная система скорректировала часы по NTP или пользователь перевёл их вручную, разность двух вызовов может оказаться даже отрицательной. performance.now() от таких скачков не зависит: он возвращает дробные миллисекунды (тип DOMHighResTimeStamp) и отсчитывает их от Performance.timeOrigin – момента старта навигации в окне или запуска воркера. Абсолютное время без риска скачков даёт формула performance.timeOrigin + performance.now().
Про точность. Разрешение Date.now() – 1 миллисекунда: несколько вызовов подряд могут вернуть одно и то же значение. Браузеры дополнительно огрубляют таймеры для защиты от тайминг-атак и фингерпринтинга: в Firefox настройка privacy.reduceTimerPrecision включена по умолчанию, и результаты кратны 2 мс, а при включённом privacy.resistFingerprinting точность падает до 100 мс. У performance.now() механизм аналогичный: 5 микросекунд в cross-origin isolated контекстах и 100 микросекунд в обычных.
Зачем это нужно
Таймстемп – компактное число, которое однозначно сортируется, легко сравнивается и не требует парсинга. Отсюда типовые задачи:
- Метки событий – зафиксировать момент действия пользователя для записи в лог или базу: число занимает меньше места, чем строка даты, и не зависит от локали.
- Ключи кэша и версии данных – пометить ответ API или запись в localStorage временем создания, чтобы понимать, когда данные устарели. Метку последнего обновления виджета удобно класть в data-атрибут элемента.
- Троттлинг обработчиков – ограничить частоту срабатывания тяжёлых обработчиков scroll или mousemove, в том числе при делегировании событий.
- Контроль дрейфа таймеров – setInterval со временем «плывёт», и самокорректирующийся таймер сверяет фактическое время именно по Date.now().
Чего Date.now() не решает: длительности измеряют через performance.now() из-за монотонности, а для сложной работы с календарными датами нужен объект Date или новый стандарт Temporal API. Часовой пояс на Date.now() не влияет: таймстемп всегда считается по UTC. Пояс появляется только при форматировании – когда из числа делают объект new Date(ts) и выводят локальную дату.
Пример
Классический сценарий из документации MDN – грубый замер времени выполнения:
const start = Date.now();
doSomeLongRunningProcess();
console.log(`Прошло ${Date.now() - start} мс`);Для коротких операций такой замер ненадёжен: шаг в 1–2 мс и зависимость от системных часов смазывают результат. Точный вариант – performance.now():
const t0 = performance.now();
doSomething();
const t1 = performance.now();
console.log(`Выполнение заняло ${t1 - t0} миллисекунд`);А вот троттлинг обработчика скролла – задача, где Date.now() на своём месте: важна не точность, а дешевизна вызова.
let last = 0;
window.addEventListener("scroll", () => {
const now = Date.now();
if (now - last < 200) return; // не чаще 5 раз в секунду
last = now;
updateProgressBar();
});Правило выбора простое: «который сейчас час» и метки событий – Date.now(); «сколько заняла операция» – performance.now().