Форматы 12-часового и 24-часового времени

Форматы времени в Cleave.js строятся на принципе маскирования ввода, при котором пользовательский ввод постепенно приводится к заранее заданному шаблону. Для работы с 12-часовым и 24-часовым представлением времени важно понимать, что библиотека не предоставляет полноценного «тайм-пикера» с внутренней логикой календаря, а опирается на конфигурацию паттернов и обработку строкового ввода.


В Cleave.js форматирование времени реализуется через комбинацию масок и ограничений на ввод символов. Основные механизмы:

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

Ключевой момент: библиотека форматирует ввод, но не является источником истинной временной логики. Это означает, что корректность диапазонов (например, 00–23 или 01–12) часто требует дополнительной обработки.


Формат 24-часового времени

24-часовой формат предполагает диапазон часов от 00 до 23. В Cleave.js он обычно реализуется через шаблон вида HH:mm или через маску с двумя числовыми блоками.

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

import Cleave from 'cleave.js';

const timeInput = new Cleave('#time24', {
  delimiters: [':'],
  blocks: [2, 2],
  numericOnly: true
});

Здесь:

  • blocks: [2, 2] задаёт структуру HH:MM;
  • delimiters: [':'] автоматически вставляет двоеточие;
  • numericOnly: true запрещает ввод любых символов, кроме цифр.

Ограничение диапазона часов

Сам Cleave.js не ограничивает значение HH диапазоном 00–23. Поэтому логика валидации добавляется отдельно:

document.querySelector('#time24').addEventListener('input', (e) => {
  const value = e.target.value;
  const [hours, minutes] = value.split(':');

  if (hours && Number(hours) > 23) {
    e.target.value = `23:${minutes || '00'}`;
  }

  if (minutes && Number(minutes) > 59) {
    e.target.value = `${hours || '00'}:59`;
  }
});

Такая схема отделяет форматирование (Cleave.js) от бизнес-логики (валидация).


Формат 12-часового времени

12-часовой формат использует диапазон 01–12 и дополнительный индикатор половины суток: AM или PM. В Cleave.js он также реализуется через маски, но требует расширенной логики.

Базовая структура:

const timeInput12 = new Cleave('#time12', {
  delimiters: [':'],
  blocks: [2, 2],
  numericOnly: true
});

Это создаёт ввод вида HH:MM, но без семантики AM/PM.


Добавление AM/PM логики

Для полноценного 12-часового формата требуется дополнительный элемент управления состоянием:

let period = 'AM';

document.querySelector('#toggle').addEventListener('click', () => {
  period = period === 'AM' ? 'PM' : 'AM';
});

Далее значение интерпретируется как связка:

  • HH:MM + period

Пример объединения:

function getFullTime() {
  const value = document.querySelector('#time12').value;
  return `${value} ${period}`;
}

Преобразование между 24h и 12h форматами

Часто требуется двунаправленное преобразование. Это выполняется вне Cleave.js.

24 → 12

function to12Hour(time24) {
  let [h, m] = time24.split(':');
  h = Number(h);

  const period = h >= 12 ? 'PM' : 'AM';
  h = h % 12 || 12;

  return `${String(h).padStart(2, '0')}:${m} ${period}`;
}

12 → 24

function to24Hour(time12, period) {
  let [h, m] = time12.split(':');
  h = Number(h);

  if (period === 'PM' && h !== 12) h += 12;
  if (period === 'AM' && h === 12) h = 0;

  return `${String(h).padStart(2, '0')}:${m}`;
}

Поведение ввода и ограничения Cleave.js

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

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

Это влияет на UX при вводе времени, особенно в 12-часовом формате, где добавляется дополнительная сущность AM/PM.


Использование кастомных обработчиков событий

Для синхронизации состояния времени часто применяется событие onValueChanged:

const cleaveTime = new Cleave('#time', {
  delimiters: [':'],
  blocks: [2, 2],
  numericOnly: true,
  onValueChanged: (e) => {
    const raw = e.target.rawValue;
    const formatted = e.target.value;

    // raw: только цифры
    // formatted: HH:MM
  }
});

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

  • хранить «сырое» значение без разделителей;
  • строить собственную модель времени;
  • синхронизировать UI с внешним состоянием приложения.

Особенности локализации

В разных регионах используются разные предпочтения:

  • 24-часовой формат (HH:mm) — стандарт в большинстве стран Европы и СНГ;
  • 12-часовой формат (hh:mm AM/PM) — распространён в США и ряде англоязычных регионов.

Cleave.js не выполняет автоматическую локализацию времени, поэтому выбор формата всегда задаётся вручную через конфигурацию интерфейса приложения.


Комбинированные сценарии

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

function switchFormat(is24) {
  cleave.destroy();

  cleave = new Cleave('#time', {
    delimiters: [':'],
    blocks: [2, 2],
    numericOnly: true
  });

  mode = is24 ? '24' : '12';
}

В таких случаях важно пересоздавать экземпляр Cleave.js, так как библиотека не предназначена для динамического изменения маски времени «на лету» без переинициализации.


Обработка некорректного ввода

Типовые проблемы при работе с временем:

  • ввод 99:99;
  • неполные значения 1:2;
  • вставка строк без разделителей 1234;
  • перепутанные границы часов.

Решение обычно строится на комбинации:

  • нормализации строки;
  • пост-валидации;
  • принудительной коррекции значений;
  • блокировки лишних символов через numericOnly.

Интеграция с формами

При использовании в формах значение времени часто синхронизируется с hidden-полями:

document.querySelector('#time24').addEventListener('input', (e) => {
  document.querySelector('#hiddenTime').value = e.target.value;
});

Это упрощает отправку данных на сервер, где Cleave.js уже не участвует.


Ограничения подхода Cleave.js для времени

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

  • отсутствие встроенной семантики времени;
  • необходимость ручной валидации диапазонов;
  • отсутствие поддержки временных зон;
  • невозможность работы с реальными объектами Date без внешней логики.

Поэтому Cleave.js рассматривается как инструмент форматирования ввода, а не как полноценный компонент управления временем.