Длительность по ISO

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

Базовая структура длительности начинается с префикса P, после которого следуют компоненты времени:

  • Y — годы
  • M — месяцы (в первой части периода)
  • W — недели
  • D — дни
  • T — разделитель времени
  • H — часы
  • M — минуты
  • S — секунды

Общий формат

P[nY][nM][nW][nD]T[nH][nM][nS]

Примеры:

  • P1Y — 1 год
  • P2M — 2 месяца
  • P10DT3H — 10 дней и 3 часа
  • P1Y2M10DT2H30M15S — комплексная длительность
  • PT45M — 45 минут
  • PT0.5S — половина секунды

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


Поддержка ISO 8601 длительностей в Day.js

Работа с длительностями в Day.js реализуется через плагин duration. Он добавляет возможность создавать, парсить и оперировать временными интервалами, включая ISO 8601 строки.

Подключение плагина:

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

dayjs.extend(duration)

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


Парсинг ISO 8601 длительности

Day.js поддерживает создание длительности из строки ISO 8601:

const d = dayjs.duration('P1Y2M10DT5H30M15S')

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


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

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

const d = dayjs.duration('P1Y2M10DT5H30M15S')

d.years()    // 1
d.months()   // 2
d.days()     // 10
d.hours()    // 5
d.minutes()  // 30
d.seconds()  // 15

Следует учитывать, что месяцы и годы не переводятся автоматически в дни.


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

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

const d = dayjs.duration('PT2H')

d.asMilliseconds() // 7200000

Также доступны альтернативные представления:

d.asSeconds()
d.asMinutes()
d.asHours()
d.asDays()

Каждое значение является нормализованным числом с плавающей точкой.


Формирование ISO 8601 строки из длительности

Day.js позволяет преобразовать длительность обратно в ISO-строку:

const d = dayjs.duration({
  years: 1,
  months: 2,
  days: 10,
  hours: 5,
  minutes: 30,
  seconds: 15
})

d.toISOString()
// "P1Y2M10DT5H30M15S"

Такое преобразование полезно при сериализации данных или передаче через API.


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

Помимо ISO-строки, поддерживается объектный формат:

const d = dayjs.duration({
  days: 7,
  hours: 12
})

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


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

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

const base = dayjs('2026-01-01')

const result = base.add(dayjs.duration('P1M10D'))

result.format('YYYY-MM-DD')
// "2026-02-11"

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


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

Аналогично добавлению выполняется вычитание:

const base = dayjs('2026-01-01')

const result = base.subtract(dayjs.duration('P10D'))

result.format('YYYY-MM-DD')
// "2025-12-22"

Особенности работы с ISO длительностями

Неравномерность единиц

Годы и месяцы не имеют фиксированного количества дней. Это означает:

  • P1M может означать 28, 29, 30 или 31 день
  • P1Y зависит от наличия високосного года

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


Отсутствие “абсолютной” длительности

ISO 8601 допускает как календарные, так и временные единицы, поэтому одна и та же строка может интерпретироваться по-разному в зависимости от контекста вычислений.


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

Day.js не выполняет агрессивную нормализацию сложных интервалов:

dayjs.duration({
  minutes: 90
})

Результат остаётся в виде минут, а не автоматически преобразуется в часы и минуты, если явно не запрашивается форматирование.


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

Прямое сравнение объектов длительности требует перевода в числовую форму:

const a = dayjs.duration('PT2H')
const b = dayjs.duration('PT90M')

a.asMinutes() > b.asMinutes() // true

Сравнение через компоненты (например, .hours()) может быть некорректным из-за разного представления данных.


Практическое использование ISO длительностей

ISO 8601 длительности применяются в API, планировщиках задач и системах расписаний:

  • таймеры и обратный отсчёт
  • SLA-ограничения
  • планирование событий
  • интервалы повторений
  • кэширование с TTL

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