Валидация периодов времени

Работа с временными интервалами в JavaScript почти всегда выходит за рамки простой проверки строк. Периоды времени требуют согласованности форматов, корректного сравнения границ и учёта нюансов календаря: часовые пояса, переходы между датами, локальные форматы представления. Библиотека Validator.js предоставляет набор инструментов, которые позволяют строить базовую и расширяемую систему валидации временных значений.


Представление времени как объекта валидации

В контексте проверки периодов времени важно понимать, что любая временная сущность в прикладной логике сводится к одному из трёх вариантов:

  • одиночная дата/время (например, 2026-05-11T10:30:00Z)
  • начало и конец интервала
  • строковое представление времени, требующее нормализации

Основная проблема при валидации — не сам факт существования даты, а её сопоставимость с другими значениями.

Validator.js ориентирован на работу со строками, поэтому временные значения обычно проверяются через предопределённые или комбинированные правила.


Проверка корректности формата даты и времени

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

Наиболее часто используется ISO 8601 как универсальный формат:

  • 2026-05-11
  • 2026-05-11T14:00:00Z
  • 2026-05-11T14:00:00+06:00

В Validator.js для таких проверок применяется:

  • isISO8601(str) — проверка строки на соответствие стандарту
  • isDate(str) — более широкая проверка, допускающая разные форматы

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

import validator from "validator";

validator.isISO8601("2026-05-11T14:00:00Z"); // true
validator.isISO8601("11-05-2026"); // false

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


Базовая проверка временных границ

Период времени определяется двумя значениями:

  • начало (start)
  • конец (end)

Основное правило корректного интервала:

начало всегда должно быть меньше конца

Для этого используется сравнение через функции isBefore и isAfter.

В Validator.js:

  • isBefore(date, dateToCompare) — проверяет, что первая дата раньше второй
  • isAfter(date, dateToCompare) — проверяет, что первая дата позже второй

Пример:

validator.isBefore("2026-05-10", "2026-05-11"); // true
validator.isAfter("2026-05-12", "2026-05-11");  // true

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

function isValidInterval(start, end) {
  return validator.isISO8601(start) &&
         validator.isISO8601(end) &&
         validator.isBefore(start, end);
}

Проверка равенства границ и нулевых интервалов

Особый случай — когда начало и конец совпадают. Такие интервалы могут быть:

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

Проверка равенства обычно реализуется через комбинацию:

  • нормализации даты
  • сравнения строк или timestamp-представлений

Validator.js не предоставляет отдельной функции строгого равенства дат, поэтому используется приведение:

function isZeroLengthInterval(start, end) {
  return new Date(start).getTime() === new Date(end).getTime();
}

Проверка длительности интервала

Валидация периодов часто требует ограничения по длине:

  • минимальная длительность (например, не менее 1 минуты)
  • максимальная длительность (например, не более 30 дней)

Логика строится на вычислении разницы:

function getDurationMs(start, end) {
  return new Date(end) - new Date(start);
}

Далее проверяется диапазон:

function isValidDuration(start, end, minMs, maxMs) {
  const diff = getDurationMs(start, end);
  return diff >= minMs && diff <= maxMs;
}

Такая логика выходит за пределы стандартных функций Validator.js, но дополняет её типичный сценарий использования.


Учет часовых поясов

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

Строки:

  • 2026-05-11T10:00:00Z
  • 2026-05-11T10:00:00+03:00

представляют разные абсолютные моменты времени.

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

  • приведение к UTC
  • использование ISO 8601 с зоной
  • унификация через Date

Валидация пересечений интервалов

Расширенная логика включает проверку конфликтов между периодами.

Два интервала [A_start, A_end] и [B_start, B_end] пересекаются, если:

  • A_start < B_end и A_end > B_start

Пример реализации:

function isOverlap(aStart, aEnd, bStart, bEnd) {
  return new Date(aStart) < new Date(bEnd) &&
         new Date(aEnd) > new Date(bStart);
}

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


Кастомные правила валидации временных периодов

Validator.js позволяет расширять стандартную систему через пользовательские валидаторы.

Пример подхода:

const customRules = {
  isBusinessHours: (value) => {
    const date = new Date(value);
    const hours = date.getUTCHours();
    return hours >= 9 && hours <= 18;
  }
};

Такая модель позволяет накладывать дополнительные ограничения:

  • рабочие часы
  • праздничные периоды
  • технические окна обслуживания

Типовые ошибки при валидации временных интервалов

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

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

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


Составные проверки интервалов

Реальные сценарии обычно объединяют несколько условий:

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

Пример комплексной функции:

function validatePeriod(start, end) {
  return validator.isISO8601(start) &&
         validator.isISO8601(end) &&
         validator.isBefore(start, end) &&
         !isOverlapWithExisting(start, end);
}

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