В библиотеке js-joda все операции, связанные со
временем, опираются на абстракцию источника времени —
Clock. Это центральный механизм, который определяет, как
именно вычисляется текущее время в приложении.
Clock используется всеми основными типами времени:
InstantLocalDateTimeZonedDateTimeOffsetDateTimeКлючевая идея заключается в том, что время не берётся напрямую из системы, а запрашивается через объект-источник, что позволяет контролировать, фиксировать и модифицировать временную шкалу.
Базовый вариант — системные часы, привязанные к реальному времени операционной системы.
import { Clock, ZoneId } from '@js-joda/core';
const clock = Clock.systemDefaultZone();
Также можно явно указать часовой пояс:
const clock = Clock.system(ZoneId.of('Europe/Berlin'));
Системные часы:
ClockФиксированные часы (fixed clock) позволяют зафиксировать
момент времени. Это критически важно для тестирования и
воспроизводимости поведения кода.
import { Clock, Instant, ZoneId } from '@js-joda/core';
const fixedInstant = Instant.parse('2025-01-01T10:00:00Z');
const clock = Clock.fixed(fixedInstant, ZoneId.of('UTC'));
Особенности фиксированных часов:
InstantЛюбые вызовы времени через такой Clock дают одинаковый
результат:
clock.instant(); // всегда 2025-01-01T10:00:00Z
Offset clock применяется для сдвига текущего времени относительно базового источника.
Идея заключается в том, что можно взять любой Clock и
создать поверх него новый, изменяющий момент времени на фиксированное
смещение.
import { Clock, Duration } from '@js-joda/core';
const baseClock = Clock.systemUTC();
const offsetClock = Clock.offset(baseClock, Duration.ofHours(3));
В этом случае:
baseClockOffset clock не изменяет системное время, а лишь трансформирует результат.
const nowBase = baseClock.instant();
const nowOffset = offsetClock.instant();
nowOffset.equals(nowBase.plusHours(3)); // true
Важно различать:
ZoneId — географический часовой пояс с правилами
переходаZoneOffset — фиксированное смещение без правилClock.offset — логическое смещение времени поверх
любого ClockTick clocks ограничивают точность времени, округляя его до заданного интервала. Это используется для устранения излишней точности (например, наносекундной), когда она не требуется.
import { Clock } from '@js-joda/core';
const clock = Clock.tickMillis(Clock.systemUTC());
Такой clock:
const clock = Clock.tickSeconds(Clock.systemUTC());
Поведение:
const clock = Clock.tickMinutes(Clock.systemUTC());
В этом случае:
Tick clock не создаёт новое время, а преобразует результат базового
Clock.
Для каждого вызова:
Instant из базового clockПример логики:
2026-01-01T12:34:56.789Z
→ tickSeconds
2026-01-01T12:34:56Z
Offset и tick clocks могут использоваться вместе, создавая составные источники времени.
const base = Clock.systemUTC();
const offset = Clock.offset(base, Duration.ofHours(2));
const ticked = Clock.tickSeconds(offset);
Поведение:
Все типы clock в js-joda подчиняются общей модели:
systemClock — отражает реальное времяfixedClock — замороженное времяoffsetClock — сдвинутое времяtickClock — округлённое времяЭта архитектура позволяет строить цепочки трансформаций:
System Clock → Offset Clock → Tick Clock → Instant
При использовании Clock все высокоуровневые типы времени
наследуют его поведение.
import { ZonedDateTime } from '@js-joda/core';
const zdt = ZonedDateTime.now(clock);
Результат зависит от типа clock:
ZoneOffset представляет фиксированное смещение от UTC и
часто используется совместно с OffsetDateTime.
import { OffsetDateTime, ZoneOffset } from '@js-joda/core';
const offset = ZoneOffset.ofHours(5);
const odt = OffsetDateTime.now(Clock.systemUTC().withZone(offset));
Хотя Clock и ZoneOffset решают разные
задачи, их комбинация позволяет:
Tick и offset clocks часто комбинируются для устранения нестабильности тестов:
Пример стабильного источника:
const stableClock = Clock.tickSeconds(
Clock.offset(
Clock.fixed(Instant.parse('2025-01-01T00:00:00Z'), ZoneOffset.UTC),
Duration.ofHours(1)
)
);