Форматирование дат

В библиотеке js-joda форматирование дат и времени реализуется через объект DateTimeFormatter. Он выполняет две ключевые задачи: преобразование объектов даты/времени в строку и обратное преобразование строки в объект временной шкалы. В отличие от стандартного Date в JavaScript, js-joda опирается на неизменяемые (immutable) типы и строгую модель времени, где форматирование отделено от самих данных.

Форматтеры создаются либо через предопределённые константы, либо через описание шаблона, либо через построитель.

Базовое использование:

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

const date = LocalDate.of(2026, 1, 24);

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

Результатом будет строка вида:

24-01-2026

Форматтер не изменяет исходный объект, а лишь описывает правила преобразования.

Шаблоны и структура паттернов

Шаблон форматирования задаётся строкой, где каждый символ имеет специальное значение. Основные элементы паттернов:

  • y — год
  • M — месяц
  • d — день месяца
  • H — часы (0–23)
  • m — минуты
  • s — секунды

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

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

Первый вариант даёт фиксированную ширину:

2026-01-24

Второй — сокращённый:

26-1-24

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

Форматирование LocalDate, LocalTime и LocalDateTime

Каждый тип времени поддерживает собственный набор доступных полей. LocalDate работает только с датой, LocalTime — только со временем, а LocalDateTime объединяет оба представления.

LocalDate

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

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

const formatter = DateTimeFormatter.ofPattern('dd MMMM yyyy');
date.format(formatter);

Результат зависит от локали и может выглядеть как:

24 May 2026

LocalTime

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

const time = LocalTime.of(14, 35, 50);

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

Результат:

14:35:50

LocalDateTime

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

const dt = LocalDateTime.of(2026, 5, 24, 14, 35);

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

Результат:

2026-05-24 14:35

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

ZonedDateTime добавляет контекст временной зоны, что влияет как на вычисления, так и на форматирование.

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

const zdt = ZonedDateTime.now(ZoneId.of('Europe/Paris'));

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

Здесь символ z отвечает за отображение краткого обозначения временной зоны.

Расширенные символы:

  • Z — смещение от UTC (+0100)
  • z — текстовое имя зоны
  • O — сокращённый формат смещения

Пример:

2026-05-24 14:35 CET

Работа с зонами требует внимательности: форматирование отображает уже преобразованное локальное время, зависящее от ZoneId.

Локализация и Locale

Форматирование может учитывать региональные настройки через Locale. Это влияет на отображение месяцев, дней недели и структуры даты.

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

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

const formatter = DateTimeFormatter
  .ofPattern('d MMMM yyyy')
  .withLocale(Locale.FRANCE);

date.format(formatter);

Результат:

24 mai 2026

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

Символы шаблона и их поведение

Система паттернов js-joda основана на строгой спецификации, близкой к Java DateTimeFormatter.

Основные группы символов:

Числовые поля

  • y — год
  • M — месяц
  • d — день
  • H — часы 24h
  • h — часы 12h
  • m, s — минуты и секунды

Текстовые поля

  • M (MMMM) — полное название месяца
  • E — день недели
  • a — AM/PM

Смещения и зоны

  • Z — +0000
  • X — +00:00
  • z — Europe/Paris

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

Любой текст, не являющийся символом форматирования, должен быть заключён в одинарные кавычки:

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

Результат:

Дата: 24.05.2026

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

Предопределённые форматтеры

js-joda содержит набор стандартных форматтеров, оптимизированных для ISO и универсальных представлений.

Основные:

  • DateTimeFormatter.ISO_LOCAL_DATE
  • DateTimeFormatter.ISO_LOCAL_TIME
  • DateTimeFormatter.ISO_LOCAL_DATE_TIME
  • DateTimeFormatter.ISO_ZONED_DATE_TIME

Пример:

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

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

date.format(DateTimeFormatter.ISO_LOCAL_DATE);

Результат:

2026-05-24

Эти форматтеры обеспечивают совместимость с внешними системами и API.

Разбор строк в даты через форматтер

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

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

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

const date = LocalDate.parse('24.05.2026', formatter);

Парсинг строго соответствует шаблону. Любое отклонение формата приводит к ошибке.

Особенности:

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

Кастомные форматтеры и композиция

Форматтеры можно комбинировать и настраивать через цепочки вызовов:

const formatter = DateTimeFormatter
  .ofPattern('dd MMM yyyy')
  .withLocale(Locale.ENGLISH);

Также возможно использование билдера:

DateTimeFormatter.ofPattern('dd/MM/yyyy HH:mm')

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

Особенности неизменяемости и повторного использования

Объекты DateTimeFormatter являются immutable и потокобезопасными. Это означает:

  • один форматтер можно использовать многократно
  • нет необходимости создавать новый экземпляр для каждого вызова
  • поведение не зависит от внешнего состояния
const formatter = DateTimeFormatter.ofPattern('yyyy-MM-dd');

const a = date1.format(formatter);
const b = date2.format(formatter);

Такой подход снижает накладные расходы при массовом форматировании.

Типичные ошибки при форматировании

Часто встречаются следующие проблемы:

  • использование неверных символов паттерна (mm вместо MM для месяцев)
  • путаница между 12- и 24-часовым форматом (h и H)
  • отсутствие экранирования текста
  • игнорирование локали при выводе месяцев
  • попытка форматировать несовместимые типы полей

Например:

DateTimeFormatter.ofPattern('mm-dd-yyyy'); // mm — минуты, а не месяц

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