Валидация корректности дат

Валидация дат в Inputmask строится на разделении синтаксической и семантической проверки. Маска отвечает за структуру ввода (формат и допустимые символы), тогда как логическая корректность даты обеспечивается набором правил, параметров алиаса datetime, предвалидацией и дополнительными проверками диапазонов.

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


Алиас datetime и базовая структура проверки

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

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

Пример базовой конфигурации:

Inputmask("datetime", {
  inputFormat: "dd/mm/yyyy",
  placeholder: "dd/mm/yyyy",
  clearIncomplete: true
}).mask(document.querySelector("input"));

На этом уровне Inputmask обеспечивает:

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

Синтаксическая и семантическая валидация

Валидация даты делится на два уровня.

Синтаксическая валидация

Обеспечивается маской и определяет:

  • соответствует ли ввод шаблону dd/mm/yyyy
  • не нарушены ли позиции сегментов
  • заполнены ли обязательные части

Пример: 32/13/2025 может пройти синтаксически, если маска не ограничивает диапазоны.


Семантическая валидация

Определяет:

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

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


Проверка диапазонов значений

Inputmask применяет диапазонные ограничения на уровне сегментов:

  • день: 01–31
  • месяц: 01–12
  • год: ограниченный диапазон (задаётся параметрами min/max)

Пример ограничения диапазона дат:

Inputmask("datetime", {
  inputFormat: "dd/mm/yyyy",
  min: "01/01/2000",
  max: "31/12/2030"
}).mask(input);

Диапазон проверяется после заполнения полей, а также частично во время ввода.


Предвалидация (prevalidator) для календарной корректности

Механизм prevalidator используется для ограничения допустимых промежуточных значений до завершения ввода сегмента.

Он особенно важен для дня и месяца, где допустимые значения зависят от контекста.

Пример логики:

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

Учет календарных правил

Количество дней в месяце

Семантическая проверка учитывает различия:

  • январь, март, май, июль, август, октябрь, декабрь → 31 день
  • апрель, июнь, сентябрь, ноябрь → 30 дней
  • февраль → 28 или 29 дней

Високосные годы

Год считается високосным при выполнении условия:

  • кратен 4
  • не кратен 100, кроме случаев кратности 400

Это влияет на допустимость даты 29 февраля.

Логика:

  • 2024 → допустим 29/02
  • 2023 → недопустим 29/02
  • 1900 → недопустим 29/02
  • 2000 → допустим 29/02

Форматы inputFormat и outputFormat

Параметр inputFormat определяет структуру ввода:

inputFormat: "dd/mm/yyyy"

Возможные варианты:

  • dd-mm-yyyy
  • mm/dd/yyyy
  • yyyy-mm-dd

outputFormat используется для преобразования значения:

outputFormat: "yyyy-mm-dd"

Это разделяет пользовательский ввод и внутреннее представление данных.


Контроль незавершённого ввода

Inputmask использует флаг незавершённости для определения валидности поля.

clearIncomplete: true

Поведение:

  • незаполненные даты очищаются при потере фокуса
  • частично введённые значения считаются невалидными

Проверка полной валидности: isComplete

Метод isComplete определяет, завершён ли ввод согласно маске:

const mask = new Inputmask("datetime", {
  inputFormat: "dd/mm/yyyy"
});

mask.isComplete(input.value);

Критерии завершённости:

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

События валидации

oncomplete

Срабатывает при полном и корректном заполнении:

Inputmask("datetime", {
  inputFormat: "dd/mm/yyyy",
  oncomplete: function () {
    console.log("Дата введена корректно");
  }
}).mask(input);

onincomplete

Срабатывает при потере фокуса с незавершённым значением:

onincomplete: function () {
  console.log("Дата не завершена");
}

Пользовательские определения и расширенная валидация

Inputmask позволяет расширять систему через definitions, что даёт возможность внедрять собственную логику проверки.

Пример расширения:

Inputmask.extendDefinitions({
  "D": {
    validator: "[0-3]",
    cardinality: 1,
    prevalidator: null
  }
});

Это позволяет:

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

Обработка вставки значений (paste validation)

При вставке строки Inputmask выполняет повторную проверку:

  • разбор строки по inputFormat
  • проверка сегментов на соответствие диапазонам
  • семантическая проверка итоговой даты

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


Пограничные случаи

Некорректные комбинации

  • 31/02/2024 → отклоняется из-за календарной логики
  • 00/12/2024 → отклоняется как недопустимый день
  • 15/13/2024 → отклоняется как недопустимый месяц

Частично валидные состояния

Во время ввода допустимы промежуточные состояния:

  • 3/
  • 12/0
  • 29/02/20

Эти значения временно принимаются до завершения проверки.


Конфликты маски и диапазона

При слишком строгой маске возможна ситуация, когда синтаксис допускает значение, но семантика его отклоняет. Например, фиксированная маска 99/99/9999 без дополнительных ограничений позволяет ввод несуществующих дат, что требует включения логических валидаторов.


Интеграция с пользовательскими проверками

Для сложных сценариев используется комбинированная валидация:

  • Inputmask обеспечивает структуру и базовые ограничения
  • внешняя логика проверяет бизнес-правила (например, допустимость дат в будущем или запрет выходных дней)

Пример дополнительной проверки:

if (new Date(value) < new Date("2000-01-01")) {
  // отклонение значения
}

Итоговая модель поведения

Валидация дат в Inputmask формируется как многоуровневая система:

  1. Маска задаёт структуру ввода
  2. datetime обеспечивает базовую семантику
  3. prevalidator ограничивает промежуточные значения
  4. календарные правила проверяют реальность даты
  5. события фиксируют состояние завершённости
  6. пользовательские расширения добавляют бизнес-логику