Библиотека js-joda реализует модель работы с датой и временем, основанную на неизменяемых (immutable) объектах. Любая операция над датой или временем не изменяет исходный объект, а возвращает новый экземпляр с результатом преобразования.
Ключевой принцип:
каждая операция = новый объект
Это критично для предсказуемости поведения в асинхронных и распределённых системах.
Для выполнения арифметических операций используются методы вида:
plusX(...) — добавлениеminusX(...) — вычитаниегде X обозначает единицу времени.
import { LocalDate } from '@js-joda/core';
const date = LocalDate.parse('2026-05-24');
const nextWeek = date.plusDays(7);
const lastWeek = date.minusDays(7);
Основные методы:
plusDays(n) / minusDays(n)plusWeeks(n) / minusWeeks(n)plusMonths(n) / minusMonths(n)plusYears(n) / minusYears(n)Особенность календарной арифметики заключается в нормализации дат. Например, добавление месяца к 31 января приведёт к корректировке дня:
LocalDate.parse('2026-01-31').plusMonths(1);
// 2026-02-28 (или 29 в високосный год)
import { LocalTime } from '@js-joda/core';
const time = LocalTime.parse('10:30');
const later = time.plusHours(2);
const earlier = time.minusMinutes(15);
Поддерживаемые единицы:
time.plusSeconds(90); // автоматическая нормализация
Переполнение времени корректно переносится внутри суток:
LocalTime.parse('23:50').plusMinutes(20);
// 00:10
LocalDateTime объединяет дату и время и поддерживает
полную арифметику календаря и времени.
import { LocalDateTime } from '@js-joda/core';
const dt = LocalDateTime.parse('2026-05-24T10:30');
const updated = dt
.plusDays(1)
.plusHours(3)
.minusMinutes(15);
Особенность комбинированных операций заключается в каскадной нормализации:
Для точных временных интервалов используется
Duration.
import { Duration } from '@js-joda/core';
const duration = Duration.ofHours(5).plusMinutes(30);
Применение к времени:
const result = LocalTime.parse('08:00').plus(duration);
ofDays(n)ofHours(n)ofMinutes(n)ofSeconds(n)ofMillis(n)Period используется для работы с датами в календарных
единицах (годы, месяцы, дни).
import { Period } from '@js-joda/core';
const period = Period.ofMonths(2).plusDays(10);
Применение:
LocalDate.parse('2026-01-01').plus(period);
Различие между Period и Duration:
Period → календарная логика (месяцы, годы)Duration → точное время (секунды, наносекунды)Операции сравнения основаны на методах:
isBeforeisAfterisEqualconst a = LocalDate.parse('2026-01-01');
const b = LocalDate.parse('2026-06-01');
a.isBefore(b); // true
b.isAfter(a); // true
Сравнение учитывает тип объекта:
LocalDate сравнивает только датуLocalTime — только времяLocalDateTime — оба компонентаДля вычисления разницы используется метод until.
const start = LocalDate.parse('2026-01-01');
const end = LocalDate.parse('2026-01-10');
const days = start.until(end).getDays();
start.until(end, ChronoUnit.DAYS);
ChronoUnit определяет единицы измерения для операций
разницы и округления.
import { ChronoUnit, LocalDateTime } from '@js-joda/core';
const a = LocalDateTime.parse('2026-01-01T00:00');
const b = LocalDateTime.parse('2026-01-02T12:00');
ChronoUnit.HOURS.between(a, b); // 36
ChronoUnit.DAYS.between(a, b); // 1
Основные единицы:
import { LocalTime, ChronoUnit } from '@js-joda/core';
LocalTime.parse('10:45:33').truncatedTo(ChronoUnit.MINUTES);
// 10:45
Усечение обнуляет младшие единицы.
Для сложных правил изменения даты используются корректоры.
import { TemporalAdjusters, LocalDate } from '@js-joda/core';
LocalDate.parse('2026-01-10')
.with(TemporalAdjusters.lastDayOfMonth());
LocalDate.parse('2026-05-24')
.with(TemporalAdjusters.firstDayOfYear());
LocalDate.parse('2026-05-24')
.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
Метод with используется для точечной замены компонентов
даты или времени:
const date = LocalDate.parse('2026-05-24');
date.withMonth(1); // замена месяца
date.withDayOfMonth(1);
date.withYear(2030);
Все операции возвращают новый объект.
js-joda автоматически корректирует значения при выходе за пределы диапазона:
LocalDate.parse('2026-10-31').plusMonths(1);
// 2026-11-30
LocalTime.parse('23:59').plusMinutes(2);
// 00:01
Благодаря неизменяемости возможно построение цепочек преобразований:
const result = LocalDateTime.parse('2026-01-01T00:00')
.plusMonths(2)
.plusDays(10)
.minusHours(3)
.withMinute(30);
Каждый шаг возвращает новый объект, сохраняя промежуточную корректность состояния.
Операции над датой часто применяются в сценариях:
Пример расчёта срока подписки:
const start = LocalDate.now();
const end = start.plusMonths(1).minusDays(1);
Часто требуется вычисление начала и конца периода.
const startOfDay = LocalDateTime.now()
.withHour(0)
.withMinute(0)
.withSecond(0);
const endOfDay = LocalDateTime.now()
.withHour(23)
.withMinute(59)
.withSecond(59);
js-joda позволяет переходить между представлениями времени:
const date = LocalDate.now();
const dateTime = date.atStartOfDay();
const time = LocalTime.now();
const dateTime2 = LocalDate.now().atTime(time);
Хотя LocalDateTime не содержит зоны,
ZonedDateTime добавляет контекст:
import { ZonedDateTime, ZoneId } from '@js-joda/core';
const zdt = ZonedDateTime.now(ZoneId.of('Europe/Berlin'));
Операции сохраняют корректность при переходе между зонами:
zdt.plusHours(5);
Операции с датой-временем в js-joda строятся на трёх фундаментальных механизмах:
plus/minuswithDuration и PeriodЭта модель обеспечивает строгую предсказуемость вычислений, исключает побочные эффекты и позволяет строить сложную временную логику без потери консистентности состояния.