Instant в js-joda представляет собой момент времени в UTC, измеряемый относительно эпохи Unix (1970-01-01T00:00:00Z). Это неизменяемый тип, предназначенный для точной работы с временными метками, где отсутствует привязка к часовым поясам и календарным компонентам.
Ключевая особенность Instant заключается в том, что он оперирует исключительно абсолютным временем. Любая арифметика с этим типом сводится к добавлению или вычитанию длительностей, выраженных в секундах, миллисекундах, наносекундах или через абстракцию Duration.
Instant хранит значение в виде:
Такое представление обеспечивает высокую точность и позволяет выполнять операции без потери детализации.
import { Instant } from 'js-joda';
const now = Instant.now();
const epochSeconds = now.epochSecond();
const nanoAdjustment = now.nano();
console.log(epochSeconds);
console.log(nanoAdjustment);
Любая арифметика с Instant всегда возвращает новый экземпляр, сохраняя неизменяемость исходного объекта.
Основной способ выполнения арифметики — методы plus и
minus с указанием единиц времени через ChronoUnit.
import { Instant, ChronoUnit } from 'js-joda';
const base = Instant.parse('2025-01-01T00:00:00Z');
const shiftedForward = base.plus(10, ChronoUnit.SECONDS);
const shiftedBack = base.minus(500, ChronoUnit.MILLIS);
console.log(shiftedForward.toString());
console.log(shiftedBack.toString());
Используемые единицы:
Механизм строго типизирован: попытка использовать календарные единицы (например, DAYS, MONTHS) для Instant допустима только в ограниченных случаях, и не всегда имеет смысл с точки зрения временной шкалы без часового пояса.
Более выразительный способ работы с временными интервалами —
использование Duration. Этот подход предпочтителен при
сложных вычислениях, связанных с временными интервалами.
import { Instant, Duration } from 'js-joda';
const start = Instant.parse('2025-01-01T00:00:00Z');
const duration = Duration.ofMinutes(90);
const end = start.plus(duration);
console.log(end.toString());
Аналогично выполняется вычитание:
const earlier = start.minus(Duration.ofHours(2));
Duration поддерживает:
Такой подход уменьшает вероятность ошибок, связанных с ручным управлением единицами измерения.
Instant не предназначен для работы с календарными сущностями. Следующая операция концептуально некорректна:
import { Period } from 'js-joda';
const instant = Instant.now();
// некорректно по смыслу
const result = instant.plus(Period.ofDays(1));
Причина заключается в том, что Period оперирует календарными датами (дни, месяцы, годы), которые зависят от календарной системы и часового пояса. Instant же находится вне календарного контекста.
Для подобных операций требуется преобразование в ZonedDateTime или LocalDateTime.
Instant поддерживает операции сравнения, которые часто используются совместно с арифметикой.
import { Instant } from 'js-joda';
const t1 = Instant.parse('2025-01-01T00:00:00Z');
const t2 = t1.plusSeconds(30);
console.log(t2.isAfter(t1));
console.log(t1.isBefore(t2));
console.log(t1.compareTo(t2));
Дополнительно доступен метод until, позволяющий
вычислить разницу между моментами времени в выбранной единице.
import { ChronoUnit } from 'js-joda';
const diff = t1.until(t2, ChronoUnit.SECONDS);
console.log(diff);
Результат будет отрицательным или положительным в зависимости от порядка аргументов.
Для частых операций предусмотрены удобные методы:
const base = Instant.parse('2025-01-01T00:00:00Z');
const a = base.plusSeconds(10);
const b = base.plusMillis(250);
const c = base.minusNanos(1_000);
Эти методы являются обертками над более универсальным
plus(long, unit) и minus(long, unit), но
обеспечивают лучшую читаемость и сниженный риск ошибок в выборе
единиц.
Арифметика Instant выполняется с учетом ограничений диапазона времени. При выходе за допустимые границы (слишком далеко в прошлое или будущее) возникает исключение.
Наносекундная точность может приводить к неочевидным эффектам при сложении:
const t = Instant.parse('2025-01-01T00:00:00Z');
const result = t.plusMillis(1).plusNanos(500);
Здесь результат будет корректно нормализован внутри секунды, с переносом в секунды при необходимости.
При построении цепочек временных вычислений Instant сохраняет предсказуемость благодаря неизменяемости.
import { Instant, Duration, ChronoUnit } from 'js-joda';
const base = Instant.now();
const result = base
.plus(Duration.ofMinutes(5))
.minus(120, ChronoUnit.SECONDS)
.plusMillis(250);
Каждый шаг возвращает новый объект, что делает такие цепочки безопасными в многопоточном и асинхронном окружении.
При моделировании событийной логики Instant часто используется как якорь времени:
Арифметика строится вокруг добавления фиксированных интервалов:
const createdAt = Instant.now();
const expiresAt = createdAt.plus(Duration.ofHours(24));
const isExpired = Instant.now().isAfter(expiresAt);
Такой подход исключает ошибки, связанные с часовыми поясами или переходами на летнее время.
Результаты операций над Instant часто преобразуются в другие типы js-joda:
import { ZoneId } from 'js-joda';
const zoned = result.atZone(ZoneId.of('Europe/Berlin'));
console.log(zoned.toString());
Это позволяет перейти от абсолютного времени к локальному представлению после завершения всех вычислений.
При работе с очень большими интервалами важно учитывать:
Система автоматически приводит внутреннее состояние к каноническому виду, однако логика приложения должна избегать чрезмерно длинных цепочек арифметических преобразований без необходимости.
Каждая операция над Instant следует функциональному подходу:
Это делает арифметику Instant устойчивой к побочным эффектам:
const a = Instant.now();
const b = a.plusSeconds(10);
console.log(a === b); // false