В библиотеке js-joda метод until
является универсальным инструментом для вычисления разницы между двумя
временными объектами. Он работает в рамках интерфейса
Temporal и его конкретных реализаций
(LocalDate, LocalTime,
LocalDateTime, ZonedDateTime), предоставляя
как высокоуровневые результаты (например, Period), так и
числовые значения в заданных единицах измерения.
Метод until имеет перегрузки, поведение которых зависит
от типа временного объекта и переданных аргументов.
Для календарных типов данных, таких как LocalDate,
вызов:
date1.until(date2)
возвращает объект Period, содержащий разницу в годах, месяцах и днях.
Пример:
import { LocalDate } from '@js-joda/core';
const start = LocalDate.parse('2024-01-10');
const end = LocalDate.parse('2025-03-25');
const period = start.until(end);
console.log(period.years()); // 1
console.log(period.months()); // 2
console.log(period.days()); // 15
Такой результат отражает календарную разницу, а не общее количество дней.
Для временных типов с точностью до времени суток
(LocalTime, LocalDateTime) результатом может
быть Duration, если используется соответствующий
контекст.
Вызов вида:
temporal1.until(temporal2, unit)
возвращает числовое значение, показывающее разницу в выбранной единице измерения.
Пример:
import { LocalDate, ChronoUnit } from '@js-joda/core';
const start = LocalDate.parse('2024-01-01');
const end = LocalDate.parse('2024-02-01');
const days = start.until(end, ChronoUnit.DAYS);
console.log(days); // 31
Поддерживаемые единицы берутся из ChronoUnit,
например:
ChronoUnit.DAYSChronoUnit.MONTHSChronoUnit.YEARSChronoUnit.HOURSChronoUnit.SECONDSОсобенность заключается в том, что результат всегда нормализуется к указанной единице, игнорируя более крупные или мелкие компоненты.
Метод всегда вычисляет разницу от текущего объекта к целевому:
start.until(end)
Если порядок обратный:
end.until(start)
результат будет отрицательным (для числовых единиц) или «обратным» периодом.
Для LocalDate метод until при возврате
Period учитывает календарную природу дат:
Это означает, что результат не всегда эквивалентен простому количеству дней.
Параллельно с until в js-joda используется более
низкоуровневый механизм — ChronoUnit.between и его
эквивалент в виде статического метода between у единиц
времени.
Сигнатура:
ChronoUnit.between(temporal1, temporal2)
Возвращает числовую разницу между двумя временными объектами в единицах, соответствующих используемой временной шкале.
Пример:
import { LocalDate, ChronoUnit } from '@js-joda/core';
const d1 = LocalDate.parse('2024-01-01');
const d2 = LocalDate.parse('2024-03-01');
const months = ChronoUnit.MONTHS.between(d1, d2);
console.log(months); // 2
Этот вариант эквивалентен:
d1.until(d2, ChronoUnit.MONTHS);
но используется как функциональный стиль через единицу измерения.
Оба подхода решают одну задачу — вычисление разницы, но различаются уровнем абстракции.
start.until(end, ChronoUnit.DAYS);
ChronoUnit.DAYS.between(start, end);
При использовании until и between важно
различать два подхода:
Используется в:
LocalDate.until(LocalDate)
Результат:
Пример:
const a = LocalDate.parse('2024-01-31');
const b = LocalDate.parse('2024-03-01');
const period = a.until(b);
Такой расчёт учитывает календарные переходы, поэтому месяцы могут вести себя не как фиксированное количество дней.
Используется в:
ChronoUnit.DAYS.between(a, b)
или
a.until(b, ChronoUnit.DAYS)
Результат:
Для объектов, содержащих время суток (LocalTime,
LocalDateTime), метод until работает в связке
с Duration.
Пример:
import { LocalTime } from '@js-joda/core';
const t1 = LocalTime.parse('10:15');
const t2 = LocalTime.parse('14:45');
const minutes = t1.until(t2, ChronoUnit.MINUTES);
console.log(minutes); // 270
При отсутствии единицы измерения:
t1.until(t2)
возвращается Duration, содержащий разницу в секундах и
наносекундах.
Если конечный момент раньше начального:
end.until(start, ChronoUnit.DAYS);
результат будет отрицательным числом, что позволяет использовать метод для обратных интервалов без дополнительных условий.
Некоторые комбинации временных типов приводят к исключениям:
LocalDate нельзя напрямую сравнивать с
LocalTimeLocalDateTime или
ZonedDateTimeПри работе с ZonedDateTime учитываются:
Это влияет на результат until, особенно при
использовании ChronoUnit.HOURS и более крупных единиц
времени.
const age = birthDate.until(today, ChronoUnit.YEARS);
const diff = ChronoUnit.DAYS.between(start, end);
Во многих случаях:
a.until(b, unit)
эквивалентно:
unit.between(a, b)
Различие носит в основном стилистический характер, однако выбор влияет на читаемость и архитектуру кода: объектный или функциональный подход к временным вычислениям.