ChronoLocalDate и ChronoZonedDateTime

Общая идея и назначение

ChronoLocalDate в библиотеке js-joda представляет собой расширенный тип даты, который инкапсулирует календарную дату без привязки к временной зоне и без учета времени суток. В отличие от стандартного LocalDate, данный интерфейс является частью более общей хронологической модели, где дата может принадлежать различным календарным системам (хроникам), а не только ISO-8601.

Ключевая особенность заключается в том, что ChronoLocalDate — это абстракция, позволяющая работать с датами в различных календарях (например, японском, исламском, буддийском), сохраняя единый интерфейс операций.

Календарные системы и хронологии

В основе ChronoLocalDate лежит понятие Chronology — календарной системы. В js-joda каждая дата ассоциируется с конкретной хроникой:

  • ISO (стандартный григорианский календарь)
  • другие поддерживаемые календарные системы через расширения

Таким образом, одна и та же дата может иметь разное представление в зависимости от выбранной хроники, но при этом сохраняется единая модель операций.

Основные свойства

ChronoLocalDate обладает следующими характеристиками:

  • не содержит информации о времени
  • не содержит информации о временной зоне
  • зависит от календарной системы
  • поддерживает сравнение дат между хрониками
  • используется как базовый тип для расширенных календарных моделей

Создание и получение экземпляров

В большинстве случаев напрямую ChronoLocalDate не создаётся, а получается через конкретную хронику.

Пример через ISO-хронику:

import { LocalDate } from '@js-joda/core';

const date = LocalDate.of(2026, 5, 25);

Преобразование в ChronoLocalDate происходит неявно, так как LocalDate реализует данный интерфейс.

Для нестандартных календарей используется фабрика хроники:

const chronoDate = SomeChronology.date(2026, 5, 25);

Операции с датами

ChronoLocalDate поддерживает стандартный набор операций:

Сдвиг даты

const newDate = date.plusDays(10);
const prevDate = date.minusMonths(1);

Сравнение

date.isBefore(otherDate);
date.isAfter(otherDate);
date.isEqual(otherDate);

Важно учитывать, что сравнение выполняется на уровне абсолютной временной линии, а не только внутри одной хроники.

Получение компонентов даты

date.year();
date.monthValue();
date.dayOfMonth();

Преобразование между хрониками

Одной из ключевых особенностей является возможность преобразования даты между различными календарными системами:

const isoDate = LocalDate.of(2026, 5, 25);
const otherChronoDate = SomeChronology.from(isoDate);

При этом сохраняется эквивалентность по времени, но меняется представление.

Ограничения модели ChronoLocalDate

Использование ChronoLocalDate вводит дополнительные ограничения:

  • нельзя напрямую работать с временными зонами
  • отсутствует информация о времени суток
  • операции могут требовать приведения к ISO для точных вычислений

ChronoZonedDateTime

Концепция и назначение

ChronoZonedDateTime представляет собой расширенную модель даты и времени, включающую:

  • календарную систему (хронику)
  • локальную дату и время
  • временную зону

Это один из наиболее сложных типов в js-joda, предназначенный для работы с глобальными временными данными, где важны как календарь, так и смещение относительно UTC.

Структура ChronoZonedDateTime

Объект объединяет три уровня информации:

  1. ChronoLocalDateTime — локальная дата и время
  2. ZoneId — идентификатор временной зоны
  3. Instant — абсолютный момент времени

Эта комбинация обеспечивает точное позиционирование момента во времени в любой системе отсчета.

Создание ChronoZonedDateTime

Чаще всего используется связывание локального времени с зоной:

import { ZonedDateTime, ZoneId, LocalDateTime } from '@js-joda/core';

const zone = ZoneId.of('Europe/Moscow');
const localDateTime = LocalDateTime.of(2026, 5, 25, 12, 0);

const zoned = ZonedDateTime.of(localDateTime, zone);

Также возможно создание из мгновенного времени:

const zonedFromInstant = ZonedDateTime.ofInstant(instant, zone);

Работа с временными зонами

ChronoZonedDateTime позволяет выполнять операции с учетом переходов зон:

Получение зоны

const zone = zoned.zone();

Смена зоны без изменения момента времени

const converted = zoned.withZoneSameInstant(ZoneId.of('Asia/Tokyo'));

Смена зоны с сохранением локального времени

const shifted = zoned.withZoneSameLocal(ZoneId.of('Asia/Tokyo'));

Разница между этими операциями фундаментальна:

  • SameInstant сохраняет абсолютный момент времени
  • SameLocal сохраняет отображаемое локальное время

Арифметика времени

ChronoZonedDateTime поддерживает операции сложения и вычитания:

const plusHours = zoned.plusHours(5);
const minusDays = zoned.minusDays(2);

При этом учитываются переходы на летнее/зимнее время и особенности календаря зоны.

Преобразование в Instant

Одной из ключевых операций является извлечение абсолютного времени:

const instant = zoned.toInstant();

Это позволяет унифицировать все временные представления в глобальную шкалу UTC.

Сравнение ZonedDateTime

Сравнение осуществляется на основе Instant, а не локальных значений:

zoned1.isAfter(zoned2);
zoned1.isBefore(zoned2);

Это гарантирует корректность сравнения между различными часовыми поясами.

Особенности работы с календарями

Как и ChronoLocalDate, данный тип поддерживает разные хроники. Однако добавляется дополнительная сложность:

  • одна и та же абсолютная точка времени может иметь разные календарные представления
  • локальное время зависит от зоны и хроники одновременно
  • преобразования могут менять структуру даты

Типичные сценарии использования

ChronoZonedDateTime применяется в случаях, где необходимо:

  • хранить события с точной временной привязкой
  • работать с международными расписаниями
  • учитывать временные зоны пользователей
  • синхронизировать события между системами

Ограничения и сложности модели

Работа с ChronoZonedDateTime требует учета ряда факторов:

  • неоднозначность локального времени при переходе на летнее время
  • возможные сдвиги календарных систем
  • необходимость преобразования в Instant для надежных вычислений
  • различие между локальным и абсолютным временем

Взаимодействие ChronoLocalDate и ChronoZonedDateTime

Оба типа являются частью единой хронологической модели:

  • ChronoLocalDate отвечает только за календарную дату
  • ChronoZonedDateTime расширяет её до полного временного контекста

Переход между ними происходит через промежуточные представления:

const dateTime = date.atStartOfDay(zone);

или

const date = zoned.toLocalDate();

Такая связка позволяет строить многоуровневые системы времени, где календарь, локальное время и зона существуют как независимые, но совместимые измерения.