Операции с длительностью

Длительность в Day.js представляется отдельным типом данных, предназначенным для работы с промежутками времени независимо от конкретных календарных дат. В отличие от объектов момента времени, длительность описывает исключительно объём времени: количество миллисекунд, секунд, минут, часов, дней и более крупных единиц.

Для работы с длительностями используется плагин duration, подключаемый поверх базового Day.js.

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

dayjs.extend(duration)

После подключения становится доступен конструктор длительности dayjs.duration().


Создание длительности

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

const d1 = dayjs.duration(2, 'hours')
const d2 = dayjs.duration(30, 'minutes')
const d3 = dayjs.duration(7, 'days')

Поддерживаемые единицы включают:

  • milliseconds
  • seconds
  • minutes
  • hours
  • days
  • weeks
  • months (условная единица, зависит от контекста)
  • years (также условная)

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

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

const d = dayjs.duration({
  hours: 1,
  minutes: 15,
  seconds: 30
})

Такой формат удобен при формировании сложных интервалов.


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

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

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

const d = dayjs.duration(2, 'hours')

d.asMilliseconds() // 7200000

Преобразование в секунды

d.asSeconds() // 7200

Преобразование в минуты и часы

d.asMinutes() // 120
d.asHours()   // 2

Методы asX() всегда возвращают дробные значения при необходимости, не округляя результат автоматически.


Доступ к компонентам длительности

Для получения «разложенной» структуры используются методы извлечения отдельных частей интервала.

const d = dayjs.duration({
  days: 2,
  hours: 5,
  minutes: 10
})

Получение значений:

d.days()     // 2
d.hours()    // 5
d.minutes()  // 10

Важно учитывать, что эти методы возвращают остаточные значения в пределах соответствующей единицы. Например, часы не включают дни.


Арифметические операции с длительностями

Сложение длительностей

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

const d1 = dayjs.duration(1, 'hour')
const d2 = dayjs.duration(30, 'minutes')

const result = d1.add(d2.asMilliseconds(), 'milliseconds')

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

const result = dayjs.duration(d1.asMilliseconds() + d2.asMilliseconds())

Такой метод исключает неоднозначности при смешивании единиц.


Вычитание длительностей

const d1 = dayjs.duration(2, 'hours')
const d2 = dayjs.duration(45, 'minutes')

const result = dayjs.duration(d1.asMilliseconds() - d2.asMilliseconds())

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


Изменение длительности через add/subtract

Плагин предоставляет методы модификации:

const d = dayjs.duration(1, 'hour')

d.add(30, 'minutes')
d.subtract(10, 'minutes')

Поведение зависит от внутреннего представления и чаще всего используется для пошагового увеличения или уменьшения интервалов.


Нормализация длительности

При накоплении значений разных единиц часто возникает необходимость нормализации:

const d = dayjs.duration({
  minutes: 90
})

Фактически это 1 час 30 минут, но внутреннее представление может сохранять исходную форму. Для приведения к стандартному виду используется преобразование через миллисекунды и пересборка:

const normalized = dayjs.duration(d.asMilliseconds())

Сравнение длительностей

Прямое сравнение объектов длительности не всегда даёт ожидаемый результат, поэтому используется сравнение через числовое представление:

const d1 = dayjs.duration(2, 'hours')
const d2 = dayjs.duration(90, 'minutes')

d1.asMilliseconds() > d2.asMilliseconds() // true

Сравнение через asMilliseconds() является универсальным способом упорядочивания интервалов.


Форматирование длительности

Стандартный Day.js не включает расширенное форматирование длительностей, однако часто используется преобразование в читаемый вид вручную.

Базовое форматирование

const d = dayjs.duration({
  hours: 3,
  minutes: 5
})

const formatted =
  `${d.hours()}ч ${d.minutes()}м`

Нормализация для отображения

При необходимости отображения больших интервалов используется каскадное разложение:

const d = dayjs.duration(93784000, 'milliseconds')

const hours = Math.floor(d.asHours())
const minutes = d.minutes()
const seconds = d.seconds()

const formatted = `${hours}:${minutes}:${seconds}`

Работа с крупными единицами времени

Дни, месяцы и годы

const d = dayjs.duration({
  years: 1,
  months: 2,
  days: 10
})

Особенность крупных единиц заключается в их условности. Например, 1 месяц может равняться 28, 30 или 31 дню в зависимости от календаря. Поэтому операции с ними требуют осторожности.

d.asDays()
d.asMonths()
d.asYears()

Эти преобразования являются приближёнными.


Инкрементальные изменения длительности

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

let d = dayjs.duration(0)

d = dayjs.duration(d.asMilliseconds() + 1000)
d = dayjs.duration(d.asMilliseconds() + 5000)

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


Клонирование длительности

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

const original = dayjs.duration(2, 'hours')
const copy = dayjs.duration(original.asMilliseconds())

Это предотвращает побочные эффекты при параллельных вычислениях.


Перевод длительности в структуру данных

Для сериализации часто используется преобразование в объект:

const d = dayjs.duration({
  hours: 4,
  minutes: 20
})

const plain = {
  hours: d.hours(),
  minutes: d.minutes(),
  milliseconds: d.asMilliseconds()
}

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


Практика работы с таймерами

Длительности часто применяются для реализации таймеров и отсчётов:

const start = dayjs.duration(10, 'seconds')

const interval = setInterval(() => {
  const updated = dayjs.duration(start.asMilliseconds() - 1000)

  if (updated.asMilliseconds() <= 0) {
    clearInterval(interval)
  }
}, 1000)

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


Ограничения и особенности модели длительности

  • отсутствует привязка к конкретной дате и часовому поясу
  • месяцы и годы являются относительными единицами
  • операции сложения и вычитания требуют нормализации через миллисекунды
  • сравнение объектов напрямую не гарантирует корректного результата
  • форматирование реализуется вручную или через дополнительные плагины

Интеграция с датами Day.js

Длительность часто используется совместно с объектами времени:

const start = dayjs('2026-01-01')
const end = start.add(dayjs.duration(3, 'days'))

Или для вычисления разницы:

const diff = dayjs.duration(end.diff(start))

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