Создание пользовательских паттернов

Библиотека js-joda предоставляет механизм форматирования и разбора дат и времени через DateTimeFormatter, который основан на строго определённых шаблонах. Помимо стандартных ISO-форматов, поддерживается создание собственных паттернов, позволяющих адаптировать строковое представление времени под любые прикладные требования: от пользовательских интерфейсов до интеграций с внешними системами.

Основы синтаксиса паттернов

Паттерн в js-joda представляет собой строку, состоящую из специальных символов, каждый из которых соответствует определённой части даты или времени.

Основные элементы:

  • y — год
  • M — месяц
  • d — день месяца
  • H — часы (24-часовой формат)
  • m — минуты
  • s — секунды
  • S — миллисекунды

Количество повторений символа влияет на формат вывода:

  • M1 или 12
  • MM01 или 12
  • MMMJan / Feb (локализованное сокращение)
  • MMMMJanuary

Пример базового форматирования:

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

const dt = LocalDateTime.of(2026, 5, 25, 14, 30);

const formatter = DateTimeFormatter.ofPattern('yyyy-MM-dd HH:mm');
const result = dt.format(formatter);

console.log(result); // 2026-05-25 14:30

Создание пользовательского шаблона

Пользовательский паттерн строится через DateTimeFormatter.ofPattern, где строка описывает желаемую структуру вывода.

const formatter = DateTimeFormatter.ofPattern('dd/MM/yyyy HH:mm:ss');

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

Дополнительные варианты:

DateTimeFormatter.ofPattern('yyyyMMdd');        // компактный формат
DateTimeFormatter.ofPattern('dd-MM-yy');        // короткий год
DateTimeFormatter.ofPattern('HH:mm dd.MM.yyyy'); // смешанный формат

Экранирование литералов

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

const formatter = DateTimeFormatter.ofPattern("'Дата:' dd.MM.yyyy");

Результат:

Дата: 25.05.2026

Если внутри текста требуется апостроф:

const formatter = DateTimeFormatter.ofPattern("'It''s date:' dd.MM.yyyy");

Работа с локализованными элементами

Некоторые символы паттерна поддерживают локализацию:

  • E — день недели
  • MMM, MMMM — месяц
  • a — AM/PM

Пример:

const formatter = DateTimeFormatter.ofPattern('EEEE, dd MMMM yyyy');

Вывод зависит от локали, установленной в окружении или переданной в formatter:

Monday, 25 May 2026

При смене локали меняется и результат:

Понедельник, 25 мая 2026

Разбор строк с пользовательским паттерном

Паттерны используются не только для форматирования, но и для обратного преобразования строк в объекты даты.

const formatter = DateTimeFormatter.ofPattern('dd-MM-yyyy HH:mm');

const dt = LocalDateTime.parse('25-05-2026 14:30', formatter);

При несоответствии строки шаблону возникает ошибка парсинга, поскольку js-joda строго проверяет соответствие структуры.

Жёсткость и неоднозначность форматов

Некоторые паттерны могут быть неоднозначными. Например:

ddMMyy

Строка 010203 может быть интерпретирована по-разному:

  • 01.02.2003
  • 01.02.1903

js-joda не выполняет эвристическую догадку, а требует точного соответствия диапазонам и правилам разрешения значений.

Для уменьшения неоднозначности используются:

  • расширенные годы (yyyy вместо yy)
  • разделители (-, /, .)

Пользовательские комбинации форматов

Паттерны позволяют строить сложные комбинированные представления даты и времени.

const formatter = DateTimeFormatter.ofPattern(
  "dd.MM.yyyy 'в' HH:mm:ss"
);

Результат:

25.05.2026 в 14:30:00

Также возможно включение нескольких смысловых блоков:

const formatter = DateTimeFormatter.ofPattern(
  "'Дата:' dd.MM.yyyy 'Время:' HH:mm"
);

Работа с миллисекундами и точностью

Для высокоточных временных меток используется символ S:

const formatter = DateTimeFormatter.ofPattern('HH:mm:ss.SSS');

Пример результата:

14:30:15.123

Разное количество S влияет на точность:

  • S → сотые доли
  • SS → сотые и десятки миллисекунд
  • SSS → полная точность

Пользовательские шаблоны с DateTimeFormatterBuilder

Для более сложных сценариев используется DateTimeFormatterBuilder, позволяющий собирать формат пошагово.

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

Пример построения гибкого формата:

const builder = new DateTimeFormatterBuilder()
  .appendLiteral('[')
  .appendValue('year')
  .appendLiteral('-')
  .appendValue('monthOfYear')
  .appendLiteral('-')
  .appendValue('dayOfMonth')
  .appendLiteral(' ')
  .appendValue('hourOfDay')
  .appendLiteral(':')
  .appendValue('minuteOfHour')
  .appendLiteral(']');

Такой подход позволяет:

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

Условные и опциональные части

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

const formatter = new DateTimeFormatterBuilder()
  .appendValue('year')
  .appendOptional(
    new DateTimeFormatterBuilder()
      .appendLiteral('-')
      .appendValue('monthOfYear')
      .appendLiteral('-')
      .appendValue('dayOfMonth')
  )
  .toFormatter();

Такой формат может работать как с полной датой, так и только с годом.

Пользовательские числовые форматы

Для числовых компонентов можно управлять шириной и заполнением:

  • фиксированная ширина
  • ведущие нули
  • минимальные и максимальные значения

Пример:

DateTimeFormatter.ofPattern('yyyy-MM-dd');
DateTimeFormatter.ofPattern('yyyy-M-d');

Разница проявляется в строгом или свободном представлении даты.

Сложные текстовые шаблоны

Паттерны могут включать произвольные текстовые конструкции, что позволяет формировать человекочитаемые строки:

const formatter = DateTimeFormatter.ofPattern(
  "yyyy 'год,' MM 'месяц,' dd 'день'"
);

Результат:

2026 год, 05 месяц, 25 день

Особенности обратного парсинга

При разборе строк важны следующие аспекты:

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

Пример:

const formatter = DateTimeFormatter.ofPattern('yyyy-MM-dd');

LocalDate.parse('2026-05-25', formatter);

Любое отклонение:

2026/05/25

приведёт к ошибке.

Комбинирование нескольких уровней форматирования

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

const dateFormatter = DateTimeFormatter.ofPattern('yyyy-MM-dd');
const timeFormatter = DateTimeFormatter.ofPattern('HH:mm:ss');

Далее результаты объединяются на уровне бизнес-логики:

2026-05-25 + 14:30:00

Управление читаемостью и стабильностью форматов

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

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

Строгие форматы (yyyy-MM-dd'T'HH:mm:ss) предпочтительны для системного взаимодействия, тогда как гибкие (dd.MM.yyyy HH:mm) применяются в пользовательских интерфейсах.