Работа с миллисекундами

В Day.js любая дата фактически опирается на стандартную UNIX-модель времени — количество миллисекунд, прошедших с 1 января 1970 года (UTC). Это значение используется как базовый числовой формат, с которым работают почти все операции сравнения, арифметики и преобразования.

Внутреннее представление можно получить и использовать напрямую:

import dayjs from 'dayjs'

const now = dayjs()
const ms = now.valueOf()

Метод valueOf() возвращает именно миллисекунды, а не объект-обёртку. Это делает Day.js совместимым с нативным Jav * aScript:

const jsDate = new Date()
const dayjsDate = dayjs()

jsDate.getTime() === dayjsDate.valueOf() // true

Получение текущих миллисекунд

Существует несколько эквивалентных способов получения текущего времени в миллисекундах:

const a = Date.now()
const b = dayjs().valueOf()

Оба варианта возвращают одно и то же значение, однако Day.js предоставляет единый интерфейс для дальнейших операций с этим числом, не требуя перехода к Date.

Также можно использовать явное преобразование:

const now = dayjs()
const ms = +now

Unary оператор + вызывает тот же механизм приведения к числу, что и valueOf().

Создание даты из миллисекунд

Day.js позволяет напрямую создавать объект даты из числового значения:

const timestamp = 1700000000000
const date = dayjs(timestamp)

В этом случае число интерпретируется как миллисекунды UNIX-эпохи. Это важно: Day.js не использует секунды по умолчанию, в отличие от некоторых API.

При работе с внешними источниками данных часто встречаются UNIX-времена в секундах. Их необходимо преобразовывать:

const unixSeconds = 1700000000
const date = dayjs(unixSeconds * 1000)

Разница между unix() и valueOf()

Day.js предоставляет два разных метода, возвращающих числовые значения времени:

  • valueOf() — миллисекунды
  • unix() — секунды
const d = dayjs()

d.valueOf() // 1700000000000
d.unix()    // 1700000000

Эта разница критична при интеграции с API, где часто используется секундная точность. Ошибка в единицах измерения приводит к смещению времени на десятки тысяч раз.

Преобразование между форматами выполняется явно:

const ms = dayjs().valueOf()
const sec = dayjs().unix()

const backToMs = sec * 1000

Арифметика с миллисекундами

Хотя Day.js предоставляет высокоуровневые методы add и subtract, миллисекунды можно использовать напрямую как базовую единицу времени.

const start = dayjs()

const later = start.add(500, 'millisecond')

Единица 'millisecond' является наименьшей в Day.js и не требует дополнительной конфигурации.

Эквивалентная операция через число:

const start = dayjs()
const later = dayjs(start.valueOf() + 500)

Оба подхода дают одинаковый результат, однако первый предпочтительнее, так как сохраняет читаемость и учитывает внутренние оптимизации библиотеки.

Вычитание и разница во времени

Метод diff возвращает разницу между датами. По умолчанию результат выражается в миллисекундах:

const a = dayjs('2025-01-01')
const b = dayjs('2025-01-01 00:00:01')

b.diff(a) // 1000

Явное указание единицы делает поведение более предсказуемым:

b.diff(a, 'millisecond') // 1000

При этом можно менять точность:

b.diff(a, 'second') // 1
b.diff(a, 'minute') // 0

Если требуется строгое получение миллисекунд, используется:

b.diff(a, 'millisecond')

Работа с временными интервалами через миллисекунды

Хотя Day.js не имеет встроенного типа Duration по умолчанию, существует plugin duration, который позволяет работать с временными промежутками более явно.

import duration from 'dayjs/plugin/duration'
import dayjs from 'dayjs'

dayjs.extend(duration)

Создание интервала в миллисекундах:

const d = dayjs.duration(1500, 'millisecond')

Также допускается передача чистого числа:

const d = dayjs.duration(1500)

Это интерпретируется как миллисекунды.

Извлечение значения обратно:

d.asMilliseconds() // 1500

Нормализация значений времени

При работе с миллисекундами часто возникает необходимость нормализации входных данных. Например, API может возвращать строки, секунды или смешанные форматы.

Базовый подход заключается в приведении всех значений к миллисекундам:

function toMs(input) {
  if (typeof input === 'number') {
    return input < 1e12 ? input * 1000 : input
  }
  return dayjs(input).valueOf()
}

Такой приём позволяет унифицировать обработку временных значений перед передачей в Day.js.

Сравнение дат через миллисекунды

Поскольку valueOf() возвращает числовое значение, сравнение дат можно выполнять напрямую:

const a = dayjs('2025-01-01')
const b = dayjs('2025-01-02')

a.valueOf() < b.valueOf() // true

Это эквивалентно использованию методов isBefore и isAfter, но может быть полезно в низкоуровневых алгоритмах.

Инкремент времени с использованием миллисекунд

Day.js поддерживает добавление произвольных чисел миллисекунд:

const base = dayjs()

const shifted = base.add(2500, 'millisecond')

Для высокочастотных операций (таймеры, throttling, debounce) часто используется именно этот подход:

const deadline = dayjs().add(16, 'millisecond')

Это особенно важно в задачах, где требуется точность ниже секунды.

Преобразование между Date и Day.js

JavaScript Date и Day.js полностью совместимы через миллисекунды:

const d1 = new Date()
const d2 = dayjs(d1)

const backToDate = new Date(d2.valueOf())

Таким образом, миллисекунды выступают универсальным мостом между двумя представлениями времени.

Потери точности и ограничения

Несмотря на то что миллисекунда считается достаточно точной единицей для большинства приложений, важно учитывать ограничения Jav * aScript:

  • точность Number ограничена 53 битами
  • при работе с очень большими timestamp возможны округления
  • высокочастотные таймеры могут накапливать дрейф

Day.js не компенсирует эти ограничения, так как опирается на стандартный числовой тип.

Практика использования в реальных сценариях

В типичных приложениях миллисекунды используются в нескольких ключевых сценариях:

  • измерение длительности операций
  • синхронизация событий интерфейса
  • вычисление задержек и таймеров
  • работа с кэшированием по TTL

Пример измерения времени выполнения:

const start = Date.now()

// операция
for (let i = 0; i < 1e6; i++) {}

const end = Date.now()
const duration = end - start

То же через Day.js:

const start = dayjs()

// операция
for (let i = 0; i < 1e6; i++) {}

const duration = dayjs().diff(start, 'millisecond')

Оба подхода эквивалентны, но второй сохраняет единообразие в кодовой базе, где уже используется Day.js.