Создание кастомных форматов

В Pikaday управление отображением даты в поле ввода чаще всего реализуется через опцию format. Она задаёт строковый шаблон, по которому выбранная дата преобразуется в текстовое представление.

new Pikaday({
  field: document.getElementById('date'),
  format: 'DD.MM.YYYY'
});

При выборе даты календарём значение в поле автоматически преобразуется в строку вида 31.12.2026, где шаблон управляет порядком и видом компонентов даты.

Наиболее распространённые форматы:

  • DD.MM.YYYY — европейский вариант
  • MM/DD/YYYY — американский вариант
  • YYYY-MM-DD — ISO-подобный формат
  • DD MMM YYYY — формат с текстовым месяцем

Внутри Pikaday форматирование не является строго фиксированным механизмом: поведение зависит от наличия библиотеки moment.js.


Роль moment.js в системе форматирования

Если в окружении доступен moment, Pikaday делегирует ему всю работу по форматированию и парсингу дат. Это делает систему гибкой и позволяет использовать расширенные токены:

new Pikaday({
  field: document.getElementById('date'),
  format: 'dddd, Do MMMM YYYY'
});

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

Tuesday, 23rd April 2026

Поддерживаются все возможности moment, включая:

  • локализацию месяцев и дней недели
  • порядковые числительные (Do)
  • относительные форматы при дополнительной обработке

Без moment форматирование становится ограниченным и базируется на внутренней реализации JavaScript Date, которая не поддерживает сложные токены.


Кастомизация через toString и parse

Для полного контроля над преобразованием даты используются функции toString и parse. Они полностью переопределяют стандартное поведение форматирования.

new Pikaday({
  field: document.getElementById('date'),

  toString(date, format) {
    const day = String(date.getDate()).padStart(2, '0');
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const year = date.getFullYear();

    return `${year}/${month}/${day}`;
  },

  parse(dateString, format) {
    const [year, month, day] = dateString.split('/');

    return new Date(year, month - 1, day);
  }
});

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

  • финансовые системы (YYYY/MM/DD)
  • логирование (YYYYMMDD)
  • компактные формы (DDMMYY)
  • специфические протоколы обмена данными

Согласование формата отображения и парсинга

При кастомной реализации важно сохранять симметрию между toString и parse. Несоответствие приводит к некорректному восстановлению даты при повторном вводе.

Типичный сценарий ошибки:

  • toString возвращает DD-MM-YYYY
  • parse ожидает YYYY-MM-DD

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

Корректная реализация предполагает единый контракт формата:

const formatDate = (date) => {
  const d = String(date.getDate()).padStart(2, '0');
  const m = String(date.getMonth() + 1).padStart(2, '0');
  const y = date.getFullYear();
  return `${d}-${m}-${y}`;
};

const parseDate = (str) => {
  const [d, m, y] = str.split('-');
  return new Date(y, m - 1, d);
};

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

При включённой возможности редактирования поля пользователь может вводить дату вручную. В этом случае parse становится критически важным элементом.

Пикейдэй использует его для:

  • проверки корректности строки
  • преобразования значения в объект Date
  • синхронизации календаря с введённым значением

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

Пример защиты от некорректного ввода:

parse(dateString) {
  const parts = dateString.split('.');

  if (parts.length !== 3) {
    return new Date();
  }

  const [day, month, year] = parts.map(Number);

  if (!day || !month || !year) {
    return new Date();
  }

  return new Date(year, month - 1, day);
}

Использование нескольких форматов в одной логике

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

  • 2026-12-31
  • 31.12.2026
  • 31/12/2026

В этом случае parse реализует ветвление логики:

parse(str) {
  let parts;

  if (str.includes('-')) {
    parts = str.split('-');
    return new Date(parts[0], parts[1] - 1, parts[2]);
  }

  if (str.includes('.')) {
    parts = str.split('.');
    return new Date(parts[2], parts[1] - 1, parts[0]);
  }

  if (str.includes('/')) {
    parts = str.split('/');
    return new Date(parts[2], parts[1] - 1, parts[0]);
  }

  return new Date(str);
}

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


Локализация форматов и региональные стандарты

Форматирование даты тесно связано с локализацией. Pikaday не предоставляет полноценную i18n-систему, но через format и moment.locale() можно добиться регионального поведения.

Пример для русской локали:

moment.locale('ru');

new Pikaday({
  field: document.getElementById('date'),
  format: 'DD MMMM YYYY'
});

Результат:

23 апреля 2026

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


Синхронизация формата с серверными API

Часто формат отображения отличается от формата передачи данных на сервер. В таких случаях Pikaday используется только как UI-слой, а сериализация выполняется отдельно.

Пример:

const picker = new Pikaday({
  field: document.getElementById('date'),
  format: 'DD.MM.YYYY',
  toString(date) {
    return date.toLocaleDateString('sv-SE'); // YYYY-MM-DD для API
  }
});

Такое разделение позволяет:

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

Ограничения кастомных форматов

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

  • потеря совместимости с moment-шаблонами
  • необходимость ручной обработки ошибок
  • рост сложности поддержки нескольких локалей
  • риск рассинхронизации toString и parse

Тем не менее, гибкость Pikaday в этом аспекте позволяет адаптировать его под практически любые сценарии работы с датами, включая нестандартные доменные форматы и специализированные интерфейсы ввода.