Создание временных интервалов

В библиотеке js-joda временной интервал представляет собой непрерывный отрезок времени между двумя моментами на временной шкале. Интервалы оперируют исключительно моментами времени (Instant), а не календарными датами или локальными представлениями, что обеспечивает однозначность и отсутствие влияния часовых поясов при вычислениях.

Интервал определяется двумя границами:

  • начальный момент (inclusive)
  • конечный момент (exclusive)

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

Библиотека js-joda-extra и Interval

Класс Interval не входит в базовый пакет js-joda и предоставляется расширением:

@js-joda/extra

Он добавляет инструменты для работы с диапазонами времени и дополняет базовые сущности (Instant, Duration, ZonedDateTime).

Импорт:

import { Interval } from '@js-joda/extra'
import { Instant } from '@js-joda/core'

Создание интервала между двумя моментами

Основной способ построения интервала — метод Interval.between.

Интервал между двумя Instant

const start = Instant.parse('2025-01-01T00:00:00Z')
const end = Instant.parse('2025-01-10T00:00:00Z')

const interval = Interval.between(start, end)

Создаваемый интервал:

  • включает start
  • исключает end

Модель [start, end) обеспечивает корректную работу с последовательными диапазонами без пересечений на границах.

Создание интервала через duration

Интервал может формироваться на основе начального момента и длительности:

import { Duration } from '@js-joda/core'

const start = Instant.parse('2025-01-01T00:00:00Z')
const duration = Duration.ofDays(5)

const interval = Interval.of(start, duration)

Такой способ фиксирует начало и автоматически вычисляет конец как:

end = start + duration

Построение интервалов из локального времени

Хотя Interval работает с Instant, локальные типы могут быть преобразованы через часовой пояс:

import { ZonedDateTime, ZoneId } from '@js-joda/core'

const zone = ZoneId.of('Europe/Paris')

const start = ZonedDateTime.of(2025, 1, 1, 10, 0, 0, 0, zone).toInstant()
const end = ZonedDateTime.of(2025, 1, 2, 10, 0, 0, 0, zone).toInstant()

const interval = Interval.between(start, end)

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

Создание пустого и бесконечного интервала

Пустой интервал

const empty = Interval.between(
  Instant.parse('2025-01-01T00:00:00Z'),
  Instant.parse('2025-01-01T00:00:00Z')
)

Пустой интервал характеризуется отсутствием длительности.

Неограниченные интервалы

В js-joda допускаются интервалы с отсутствующей верхней границей:

const start = Instant.parse('2025-01-01T00:00:00Z')

const interval = Interval.from(start) // до бесконечности

И аналогично:

const interval = Interval.to(Instant.parse('2025-01-01T00:00:00Z'))

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

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

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

  • если start > end, значения меняются местами
  • интервал всегда хранится в корректной хронологической последовательности
const a = Instant.parse('2025-01-10T00:00:00Z')
const b = Instant.parse('2025-01-01T00:00:00Z')

const interval = Interval.between(a, b)
// автоматически нормализуется

Интервалы нулевой длительности

Интервал, у которого совпадают границы, считается пустым:

const instant = Instant.parse('2025-01-01T00:00:00Z')

const interval = Interval.between(instant, instant)

Такой интервал:

  • не содержит ни одного момента времени
  • возвращает true для проверки пустоты

Проверка принадлежности момента интервалу

Операция проверки включения основана на методе contains:

const instant = Instant.parse('2025-01-03T00:00:00Z')

interval.contains(instant)

Логика:

  • true — момент внутри [start, end)
  • false — вне диапазона

Пересечение интервалов

Создание интервалов позволяет выполнять операции над диапазонами времени. Пересечение определяется через метод overlaps:

const i1 = Interval.between(
  Instant.parse('2025-01-01T00:00:00Z'),
  Instant.parse('2025-01-10T00:00:00Z')
)

const i2 = Interval.between(
  Instant.parse('2025-01-05T00:00:00Z'),
  Instant.parse('2025-01-15T00:00:00Z')
)

i1.overlaps(i2)

Результат зависит от наличия общей части интервалов.

Сравнение границ при создании

При построении интервалов важно различать:

  • логическую последовательность (начало < конец)
  • фактическую нормализацию внутри объекта Interval

Даже при передаче обратных границ интервал остаётся корректным:

Interval.between(end, start)

Внутренняя структура гарантирует консистентность без внешней проверки.

Практика комбинирования интервалов

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

  • разбиение периодов
  • объединение диапазонов
  • анализ пересечений расписаний

Пример последовательных интервалов:

const day1 = Interval.between(
  Instant.parse('2025-01-01T00:00:00Z'),
  Instant.parse('2025-01-02T00:00:00Z')
)

const day2 = Interval.between(
  Instant.parse('2025-01-02T00:00:00Z'),
  Instant.parse('2025-01-03T00:00:00Z')
)

Границы согласованы так, что интервалы не пересекаются и не имеют разрывов.