Комбинированные маски даты и времени

Составные маски даты и времени в Inputmask строятся на объединении нескольких логических блоков: даты, времени и разделителей между ними. Основная задача таких масок — обеспечить строгий формат ввода, в котором пользователь не может нарушить структуру, но при этом ввод остаётся естественным и поэтапным.


Комбинированная маска обычно состоит из двух частей:

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

Между ними используется фиксированный разделитель, чаще всего пробел или символ T в формате ISO.

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

Inputmask("datetime")

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

Inputmask("99.99.9999 99:99")

Здесь:

  • 99.99.9999 — дата
  • пробел — разделитель
  • 99:99 — время

Разделение логических блоков

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

Блок даты

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

"dd.mm.yyyy"
"mm/dd/yyyy"
"yyyy-mm-dd"

В терминах Inputmask это выражается через маску:

"99.99.9999"
"99/99/9999"
"9999-99-99"

Ключевой момент: Inputmask не понимает семантику даты без дополнительных правил, поэтому он работает только с позицией символов.


Блок времени

Временные маски обычно строятся так:

"hh:mm"
"hh:mm:ss"

В Inputmask:

"99:99"
"99:99:99"

Для ограничения диапазонов используются дополнительные опции (например, валидаторы или onBeforePaste).


Объединение даты и времени в одну маску

Самый простой способ комбинирования — конкатенация двух масок:

Inputmask("99.99.9999 99:99").mask(input);

Однако такой подход имеет ограничение: отсутствие контроля допустимых значений.


Использование alias datetime

Inputmask предоставляет встроенный алиас datetime, который уже содержит базовую логику:

Inputmask("datetime").mask(input);

Этот алиас поддерживает:

  • разделение даты и времени
  • базовую проверку формата
  • локализацию (в зависимости от конфигурации)

Конфигурация datetime-маски

Расширенная настройка выполняется через объект:

Inputmask({
  alias: "datetime",
  inputFormat: "dd.mm.yyyy HH:MM"
}).mask(input);

Ключевые параметры:

  • inputFormat — задаёт структуру
  • placeholder — символы заполнения
  • separator — разделитель между компонентами

Локализация форматов

Разные регионы используют разные порядки:

  • Европа: dd.mm.yyyy
  • США: mm/dd/yyyy
  • ISO: yyyy-mm-dd

Комбинированные маски должны учитывать этот порядок:

Inputmask({
  alias: "datetime",
  inputFormat: "yyyy-mm-dd HH:MM:ss"
}).mask(input);

Управление разделителями

Разделитель между датой и временем — критический элемент. Он должен быть фиксированным, иначе маска теряет предсказуемость.

Примеры:

"99.99.9999 99:99"
"9999-99-99T99:99:99"

Второй вариант соответствует ISO 8601 и часто используется в API.


Проблема частичного ввода

При комбинированных масках важно учитывать сценарий незавершённого ввода:

  • пользователь ввёл только дату
  • пользователь начал ввод времени
  • пользователь вставил строку целиком

Для управления этим используется:

onBeforePaste: function (pastedValue) {
  return pastedValue;
}

Или более строгая фильтрация:

onBeforePaste: function (value) {
  return value.replace(/[^\d.: -]/g, "");
}

Ограничение диапазонов даты и времени

Сам Inputmask не является полноценным валидатором календаря, но позволяет частично ограничивать ввод.

Пример ограничения часов:

Inputmask({
  alias: "datetime",
  inputFormat: "dd.mm.yyyy HH:MM",
  hourFormat: "24"
}).mask(input);

Для более строгих правил применяются внешние проверки:

function validateDateTime(value) {
  const [date, time] = value.split(" ");
  const [day, month, year] = date.split(".");
  const [hour, minute] = time.split(":");

  return (
    day <= 31 &&
    month <= 12 &&
    hour < 24 &&
    minute < 60
  );
}

Маски с миллисекундами

В некоторых интерфейсах требуется высокая точность времени:

"99.99.9999 99:99:99.999"

Конфигурация:

Inputmask({
  alias: "datetime",
  inputFormat: "dd.mm.yyyy HH:MM:ss.l"
}).mask(input);

Где:

  • l — миллисекунды

Гибридные форматы с текстовыми разделителями

Допускается использование текстовых вставок:

"99.99.9999 at 99:99"

Такой подход применяется в логах и административных интерфейсах:

Inputmask("99.99.9999 'at' 99:99").mask(input);

Ключевой момент — фиксированные литералы в маске.


Обработка вставки из буфера обмена

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

2026-05-19 14:33:00

Для нормализации применяется постобработка:

onBeforePaste: function (value) {
  return value.replace("T", " ");
}

Или более универсально:

onBeforePaste: function (value) {
  return value.replace(/[TZ]/g, " ");
}

Поддержка ISO 8601

ISO-формат является наиболее устойчивым для комбинированных масок:

"yyyy-mm-dd'T'HH:MM:ss"

В Inputmask он задаётся напрямую:

Inputmask({
  alias: "datetime",
  inputFormat: "yyyy-mm-dd'T'HH:MM:ss"
}).mask(input);

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

  • символ T должен быть экранирован как литерал
  • структура строго фиксирована

Поведение курсора в комбинированных масках

При переходе между блоками (дата → время) Inputmask управляет курсором автоматически:

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

Это особенно важно в длинных масках:

"99.99.9999 99:99:99"

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

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

  1. Использование переменных разделителей → приводит к невозможности строгой маски

  2. Отсутствие единого формата даты и времени → ломает парсинг на сервере

  3. Смешивание локалей → mm.dd.yyyy и dd.mm.yyyy в одном интерфейсе

  4. Попытка заменить валидацию маской → Inputmask не заменяет бизнес-логику


Расширенные сценарии комбинирования

В сложных интерфейсах комбинированные маски включают дополнительные элементы:

  • временная зона
  • статус
  • метки

Пример:

"99.99.9999 99:99 GMT+99"

Реализация:

Inputmask("99.99.9999 99:99 'GMT+'99").mask(input);

Итоговая модель комбинированной маски

Комбинированная маска даты и времени в Inputmask строится по принципу:

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

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