В библиотеке js-joda механизм разбора дат и времени строится вокруг
строгого соответствия полей календаря и правил их интерпретации.
Центральную роль в этом процессе играет ResolverStyle,
определяющий стратегию разрешения неоднозначных и некорректных значений
при парсинге.
ResolverStyle определяет, как именно библиотека должна
интерпретировать входные данные при преобразовании строк или наборов
полей в объекты даты и времени (LocalDate,
LocalDateTime, ZonedDateTime и др.).
Он применяется в момент “разрешения” полей после их извлечения из
строки через DateTimeFormatter. На этом этапе система уже
имеет набор числовых значений (год, месяц, день, час и т.д.), но ещё не
решила, являются ли они корректной календарной комбинацией.
Основная задача ResolverStyle — определить поведение
при:
В js-joda выделяются три основных стратегии:
Строгий режим, при котором любые отклонения от календарной корректности приводят к ошибке.
Характеристики:
Пример поведения:
2021-02-30 → ошибка (февраль не имеет 30 дней)2021-04-31 → ошибка (апрель имеет 30 дней)2020-02-29 → допустимо (високосный год)STRICT используется, когда требуется абсолютная точность входных данных, например при финансовых или юридических вычислениях.
Интеллектуальный режим, балансирующий между строгостью и практической гибкостью.
Характеристики:
Примеры поведения:
2021-02-30 → 2021-02-28 (последний день
месяца)2021-04-31 → 2021-04-302021-01-32 → ошибка или корректировка в зависимости от
контекста полей (обычно ограничение до конца месяца, без перехода в
следующий)SMART часто используется в пользовательских интерфейсах, где ввод может быть неточным, но автоматическая коррекция предпочтительнее отказа.
Максимально свободный режим интерпретации, допускающий перенос значений между полями.
Характеристики:
Примеры поведения:
2021-01-32 → 2021-02-012021-12-40 → 2022-01-092021-02-60 → перенос в мартLENIENT фактически рассматривает дату как набор чисел, которые нормализуются в календарную форму.
ResolverStyle применяется через конфигурацию
форматтера:
DateTimeFormatter
.ofPattern("yyyy-MM-dd")
.withResolverStyle(ResolverStyle.STRICT);
Именно на этапе вызова parse() происходит применение
выбранной стратегии.
Разница особенно заметна при одинаковом шаблоне форматирования, но разных стилях разрешения.
Входная строка: 2021-02-31
2021-02-282021-03-03Наиболее чувствителен к ResolverStyle, так как полностью
зависит от календарной валидности.
При добавлении времени влияние LENIENT становится более заметным:
Пример:
2021-01-01T25:00 в LENIENT →
2021-01-02T01:00SMART обычно ограничивает подобные случаи более консервативно.
В сочетании с часовыми поясами LENIENT может приводить к дополнительным сдвигам:
При построении сложных форматтеров ResolverStyle влияет
на интерпретацию полей, собранных из разных источников:
appendValue() без ограничений может создавать
неоднозначные значенияПример конфликтной ситуации:
Результат:
LENIENT допускает выход за пределы 1–12:
LENIENT перераспределяет дни по календарю:
SMART ограничивает переполнение в рамках месяца.
STRICT полностью запрещает такие значения.
| Ситуация | STRICT | SMART | LENIENT |
|---|---|---|---|
| 31 апреля | ошибка | 30 апреля | 1 мая |
| 30 февраля | ошибка | 28/29 февраля | март с переносом |
| 32 января | ошибка | ошибка/ограничение | 1 февраля |
| некорректный месяц | ошибка | корректировка | перенос года |
Выбор ResolverStyle определяет не только поведение
ошибок, но и саму семантику данных:
Эти различия критичны при:
Некоторые комбинации полей не имеют единственного решения без стратегии разрешения:
STRICT требует полной согласованности всех полей.
SMART выбирает наиболее логичное представление в пределах календаря.
LENIENT преобразует все значения в единую шкалу времени с последующей нормализацией.
ResolverStyle формирует фундаментальный слой
интерпретации дат, определяя границу между:
Каждый режим задаёт собственную семантику преобразования входных данных, влияя на итоговую структуру объектов даты и времени и поведение парсера при любых отклонениях от календарной нормы.