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

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

Ключевая идея заключается в том, что длительность — это набор единиц времени, нормализуемых и преобразуемых по запросу: миллисекунды, секунды, минуты, часы, дни, месяцы и годы. Внутренне Day.js опирается на миллисекундное представление, что упрощает арифметику и унифицирует операции.


Подключение модуля длительности

Функциональность длительностей не входит в ядро Day.js и подключается через плагин.

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

dayjs.extend(duration)

После расширения становится доступен конструктор dayjs.duration, через который создаются все интервалы времени.


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

Длительность может быть задана несколькими способами: числом миллисекунд, объектом с временными единицами или строкой в ISO-формате.

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

const d1 = dayjs.duration(5000)

Значение интерпретируется как 5000 миллисекунд, что эквивалентно 5 секундам.


Создание из набора единиц

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

Каждая единица суммируется с учётом собственной шкалы. Такой подход удобен при формировании интервалов из пользовательского ввода или вычисленных значений.


Создание из строкового формата

Поддержка строк зависит от конфигурации и дополнительных плагинов, но часто используется ISO 8601 duration:

const d3 = dayjs.duration('PT2H30M15S')

Формат PT... задаёт временную часть: часы, минуты и секунды.


Внутреннее представление и нормализация

Day.js хранит длительность в миллисекундах, но при запросе отдельных единиц происходит пересчёт. Например, при вызове .hours() извлекается количество полных часов, оставшихся после деления на сутки.

const d = dayjs.duration(90061000)

d.asSeconds() // 90061
d.asMinutes() // 1501.016...
d.asHours()   // 25.016...

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


Извлечение компонент длительности

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

const d = dayjs.duration(90061000)

d.hours()   // 1
d.minutes() // 1
d.seconds() // 1

Эти методы возвращают «остаточные» значения после разложения общей длительности на более крупные единицы. Например, часы возвращаются в диапазоне 0–23.


Арифметика длительностей

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

const a = dayjs.duration({ minutes: 30 })
const b = dayjs.duration({ minutes: 20 })

const sum = dayjs.duration(a.asMilliseconds() + b.asMilliseconds())

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


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

Базовый плагин не предоставляет универсального форматирования строкового вида, поэтому применяется комбинация методов извлечения значений.

Ручное форматирование

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

const formatted =
  `${d.hours().toString().padStart(2, '0')}:` +
  `${d.minutes().toString().padStart(2, '0')}:` +
  `${d.seconds().toString().padStart(2, '0')}`

Результат:

03:05:09

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


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

При длительных интервалах важно учитывать перенос единиц:

const d = dayjs.duration(3723000) // 1 час 2 минуты 3 секунды

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

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

Человеко-читаемое представление

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

Пример базовой реализации

function formatDuration(d) {
  const parts = []

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

  if (hours) parts.push(`${hours} ч`)
  if (minutes) parts.push(`${minutes} мин`)
  if (seconds) parts.push(`${seconds} сек`)

  return parts.join(' ')
}

Особенности работы с единицами

Переполнение единиц

Day.js автоматически нормализует значения при создании:

dayjs.duration({
  minutes: 90
})

Результат интерпретируется как 1 час 30 минут при извлечении компонент.


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

Допускаются отрицательные значения, возникающие при вычитании:

const d = dayjs.duration(1000).subtract(dayjs.duration(5000))

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


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

Сравнение выполняется через приведение к единой шкале:

const a = dayjs.duration(60000)
const b = dayjs.duration(120000)

a.asMilliseconds() > b.asMilliseconds()

Непосредственного метода сравнения в базовом API нет, поэтому используется числовая форма.


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

Длительности часто применяются для смещения временных точек:

const start = dayjs('2026-01-01T10:00:00')

const shifted = start.add(dayjs.duration(2, 'hours'))

Такой механизм позволяет отделить логику интервалов от операций над датами.


Ограничения стандартного API

Базовый модуль длительности в Day.js не предоставляет:

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

Из-за этого значительная часть логики форматирования реализуется вручную или через сторонние расширения.


Практика нормализации отображения

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

function normalize(ms) {
  const d = dayjs.duration(ms)

  const days = Math.floor(d.asDays())
  const hours = d.hours()
  const minutes = d.minutes()
  const seconds = d.seconds()

  return {
    days,
    hours,
    minutes,
    seconds
  }
}

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


Форматирование больших интервалов

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

const d = dayjs.duration(900000000)

const days = Math.floor(d.asDays())
const hours = Math.floor(d.asHours()) % 24
const minutes = d.minutes()
const seconds = d.seconds()

Результат можно использовать для интерфейсов таймеров, логов или аналитики.


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

Несмотря на наличие абстракции, миллисекунды остаются основой:

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

d.asMilliseconds() // 300000

Это упрощает интеграцию с системами, где временные интервалы представлены числовыми значениями: очередями задач, таймерами, измерениями производительности.


Форматирование в фиксированные шаблоны

Распространённый сценарий — вывод в виде HH:MM:SS независимо от длины интервала:

function toClock(ms) {
  const d = dayjs.duration(ms)

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

  return [
    totalHours.toString().padStart(2, '0'),
    minutes.toString().padStart(2, '0'),
    seconds.toString().padStart(2, '0')
  ].join(':')
}

Такой формат применяется в медиаплеерах, таймерах и системах мониторинга времени выполнения операций.