Форматы дат

Joi.date() представляет собой валидатор для работы с датами в JavaScript. В основе используется стандартный объект Date, а проверка значений строится вокруг возможности преобразования входных данных в корректную дату и их дальнейшей валидации.

import Joi from 'joi';

const schema = Joi.date();

schema.validate('2026-05-10T12:00:00Z');

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


Поддерживаемые форматы дат

Валидация Joi.date() опирается на возможности Date.parse() и внутренние механизмы ECMAScript. Основные поддерживаемые форматы:

ISO 8601

Наиболее надёжный и рекомендуемый формат.

Joi.date().validate('2026-05-10T14:30:00Z');

Допустимые варианты:

  • 2026-05-10
  • 2026-05-10T14:30:00Z
  • 2026-05-10T14:30:00+05:00

ISO-формат гарантирует предсказуемость при сериализации и передаче данных между системами.


Timestamp (числовые значения)

Поддерживаются Unix timestamp в миллисекундах.

Joi.date().validate(1715347200000);

Число интерпретируется как количество миллисекунд с 1 января 1970 года UTC.

Дополнительно:

Joi.date().timestamp().validate(1715347200, 'seconds');

Метод .timestamp() позволяет явно указать единицы измерения:

  • milliseconds (по умолчанию)
  • seconds

Автоматическое преобразование типов

По умолчанию включена опция convert, позволяющая преобразовывать строки и числа в объект Date.

const schema = Joi.date();

schema.validate('2026-05-10');

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

const schema = Joi.date().strict();

schema.validate('2026-05-10'); // ошибка

Строгая валидация

Метод .strict() запрещает автоматическое приведение типов.

Joi.date().strict().validate('2026-05-10');

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

Joi.date().strict().validate(new Date());

Ограничения диапазона дат

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

Минимальная дата

Joi.date().min('2020-01-01');

Максимальная дата

Joi.date().max('2030-12-31');

Допустимы также динамические значения:

Joi.date().min('now');
Joi.date().max('now');

now интерпретируется как момент выполнения валидации.


Сравнение дат между собой

Joi позволяет задавать относительные ограничения.

const schema = Joi.object({
  start: Joi.date(),
  end: Joi.date().greater(Joi.ref('start'))
});

Поддерживаются операторы:

  • .greater()
  • .less()
  • .min()
  • .max()

Работа с точностью времени

Объект Date в JavaScript хранит время с точностью до миллисекунд. Joi не изменяет точность, но сравнение выполняется на уровне timestamp.

Joi.date().validate(new Date('2026-05-10T12:00:00.123Z'));

При необходимости игнорирования времени используется нормализация значений вне Joi (например, обнуление часов).


Обработка временных зон

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

Joi.date().validate('2026-05-10T00:00:00+03:00');

Внутренне значение приводится к UTC.

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

  • строки без временной зоны интерпретируются как локальное время
  • ISO-строки с Z фиксируются как UTC
  • сравнения происходят в UTC-формате timestamp

Валидация некорректных значений

Некоторые входные данные автоматически отклоняются:

Joi.date().validate('not-a-date'); // ошибка
Joi.date().validate('2026-13-40');  // ошибка

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


Работа с null и undefined

По умолчанию:

  • undefined проходит только при отсутствии обязательности
  • null требует явного разрешения
Joi.date().allow(null);
Joi.date().optional();

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

Для нестандартных форматов применяется .custom().

Joi.date().custom((value, helpers) => {
  const parsed = customParse(value);
  if (!parsed) {
    return helpers.error('date.invalid');
  }
  return parsed;
});

Это позволяет обрабатывать форматы вида:

  • 10/05/2026
  • 10-05-2026
  • любые доменные форматы дат

Комбинация с другими правилами

Дата часто используется в объектах с дополнительными ограничениями.

const schema = Joi.object({
  createdAt: Joi.date().max('now'),
  expiresAt: Joi.date().greater(Joi.ref('createdAt'))
});

Подобные схемы обеспечивают контроль жизненного цикла данных.


Форматирование результата

После успешной валидации результатом становится объект Date.

const { value } = Joi.date().validate('2026-05-10');
typeof value; // object
value instanceof Date; // true

При необходимости сериализации используется:

value.toISOString();

Особенности поведения при неявных преобразованиях

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

Joi.date().validate('01-02-03');

Результат зависит от реализации Date.parse() в среде выполнения, что делает подобные форматы нестабильными.


Использование с массивами дат

Joi.array().items(Joi.date().iso());

Метод .iso() ограничивает входные значения строгим ISO-форматом.


ISO-режим

Joi.date().iso().validate('2026-05-10T10:00:00Z');

В этом режиме допускаются только ISO 8601 строки, что повышает предсказуемость обработки данных.


Поведение при сериализации JSON

При использовании JSON.stringify:

JSON.stringify({ date: new Date() });

Дата автоматически преобразуется в ISO-строку, что согласуется с поведением Joi при конвертации входных данных.