В библиотеке js-joda работа с временными интервалами строится вокруг строгой типизации единиц времени. Центральную роль в этой модели играет перечисление ChronoUnit, задающее дискретные шаги измерения — от наносекунд до тысячелетий. Эти единицы используются для вычислений разницы между моментами времени, для прибавления и вычитания интервалов, а также для нормализации и преобразования дат.
ChronoUnit является аналогом
java.time.temporal.ChronoUnit из Java Time API и сохраняет
его семантику, включая поведение при граничных значениях календаря и
неоднородность календарных систем.
ChronoUnit объединяет две категории единиц:
К ним относятся:
Эти единицы имеют фиксированную продолжительность в SI-терминах (за исключением HALF_DAYS, привязанного к 12 часам). Их можно безопасно использовать для арифметики времени, не учитывающей календарные аномалии.
К ним относятся:
Они зависят от календарной структуры и не имеют фиксированной длительности в миллисекундах. Например, MONTHS может быть 28, 29, 30 или 31 день.
ChronoUnit используется как универсальный параметр для временных операций:
Метод between позволяет вычислить количество единиц
ChronoUnit между двумя значениями.
Пример для временных меток:
import { ChronoUnit, Instant } from 'js-joda';
const start = Instant.parse('2025-01-01T00:00:00Z');
const end = Instant.parse('2025-01-02T12:00:00Z');
const hours = ChronoUnit.HOURS.between(start, end);
const minutes = ChronoUnit.MINUTES.between(start, end);
Значение вычисляется как целое число полных единиц между моментами времени, с усечением дробной части.
При использовании дат без времени поведение ChronoUnit становится календарно-зависимым.
import { ChronoUnit, LocalDate } from 'js-joda';
const date1 = LocalDate.of(2025, 1, 1);
const date2 = LocalDate.of(2025, 3, 1);
const months = ChronoUnit.MONTHS.between(date1, date2);
const days = ChronoUnit.DAYS.between(date1, date2);
MONTHS учитывает календарные переходы между месяцами, тогда как DAYS оперирует фактическим количеством дней.
ChronoUnit используется в методах plus и
minus через числовые аргументы в сочетании с
Temporal-объектами.
import { ChronoUnit, LocalDateTime } from 'js-joda';
const dt = LocalDateTime.of(2025, 1, 1, 10, 0);
const result = dt.plus(3, ChronoUnit.DAYS);
Аналогично:
const result2 = dt.minus(2, ChronoUnit.MONTHS);
Календарные единицы автоматически учитывают особенности календаря, включая разную длину месяцев и високосные годы.
Не все временные типы поддерживают все ChronoUnit. Например, Instant не работает с MONTHS.
Метод isSupportedBy позволяет определить допустимость
операции:
import { ChronoUnit, Instant } from 'js-joda';
ChronoUnit.DAYS.isSupportedBy(Instant.now());
ChronoUnit.MONTHS.isSupportedBy(Instant.now());
Результат:
Это важно при построении универсальных временных функций.
HALF_DAYS представляет половину суток (12 часов). Эта единица часто используется при переходах между утренними и вечерними периодами.
ChronoUnit.HALF_DAYS.between(start, end);
Особенность заключается в том, что она не привязана к календарным границам дня, а оперирует строго фиксированными 12-часовыми интервалами.
FOREVER не представляет реального временного интервала. Это служебная единица, используемая для обозначения бесконечного периода или невозможности выразить разницу в конечных терминах.
Обычно применяется в контекстах сравнений и специальных временных политик.
ChronoUnit тесно связан с интерфейсом TemporalAccessor и TemporalAmount. Он выступает в роли универсального ключа для операций:
Пример использования until:
import { ChronoUnit, LocalTime } from 'js-joda';
const t1 = LocalTime.of(10, 0);
const t2 = LocalTime.of(15, 30);
const hours = t1.until(t2, ChronoUnit.HOURS);
Результат — количество полных часов между значениями.
При работе с MONTHS и YEARS возможны эффекты “усечения”:
ChronoUnit не интерполирует значения, а следует правилам календарной корректности, заложенным в LocalDate и LocalDateTime.
Ключевая особенность ChronoUnit заключается в различии моделей вычислений:
Пример различия:
ChronoUnit.DAYS.between(Instant.parse('2025-01-01T00:00:00Z'), Instant.parse('2025-01-02T00:00:00Z'));
ChronoUnit.MONTHS.between(LocalDate.of(2025,1,31), LocalDate.of(2025,2,28));
В первом случае результат строго детерминирован, во втором зависит от календарной структуры.
ChronoUnit часто применяется в:
При этом выбор единицы напрямую влияет на точность и поведение алгоритма при переходах через границы календаря.
js-joda реализует ChronoUnit как неизменяемый набор констант. Каждая единица содержит:
Это обеспечивает предсказуемость и отсутствие скрытых преобразований между типами времени.
При использовании ChronoUnit всегда применяется целочисленное усечение:
Пример:
ChronoUnit.HOURS.between(start, end);
Если разница составляет 5 часов 59 минут, результат будет 5.
ChronoUnit выполняет функцию универсального языка измерения времени в js-joda. Он связывает:
Через него формируется единая система операций над временными данными, исключающая неоднозначность в интерпретации интервалов.