@IsISO8601

Декоратор @IsISO8601 из библиотеки class-validator предназначен для проверки строк на соответствие формату даты и времени ISO 8601. Этот формат является международным стандартом представления дат и широко используется в API, базах данных, логах и протоколах обмена данными.

Основная задача валидатора — гарантировать, что строка представляет собой корректную дату/время в одном из допустимых вариантов ISO 8601, включая дату, дату со временем и временные зоны.


Общая спецификация ISO 8601 в контексте валидации

ISO 8601 допускает множество вариантов записи:

  • 2024-01-25
  • 2024-01-25T14:30:00
  • 2024-01-25T14:30:00Z
  • 2024-01-25T14:30:00+03:00
  • 2024-01-25T14:30:00.123Z

При этом валидатор @IsISO8601 ориентируется на строгую проверку структуры строки, а не на преобразование в объект Date. Это ключевой момент: корректность формата не всегда означает корректность календарной даты в логическом смысле JavaScript-движка.


Базовое использование

import { IsISO8601 } from 'class-validator';

class EventDto {
  @IsISO8601()
  startDate: string;
}

В этом случае поле startDate должно содержать строку, соответствующую стандарту ISO 8601. Любое отклонение от формата приведёт к ошибке валидации.


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

Валидатор выполняет следующие проверки:

  • строка должна быть непустой (если не используются дополнительные декораторы вроде @IsOptional)
  • формат должен соответствовать ISO 8601
  • допускаются временные зоны (Z, +hh:mm, -hh:mm)
  • допускается миллисекундная часть времени

Примеры валидных значений:

2024-01-01
2024-01-01T00:00:00Z
2024-01-01T00:00:00+00:00
2024-01-01T12:45:30.500Z

Примеры невалидных значений:

01-01-2024
2024/01/01
2024-1-1
2024-01-01 12:00:00
yesterday

Строгий режим strict

Декоратор поддерживает параметр strict, который усиливает проверку формата.

class TaskDto {
  @IsISO8601({ strict: true })
  deadline: string;
}

Поведение строгого режима:

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

Пример различий:

Значение Без strict С strict
2024-01-01 валидно валидно
20240101 может пройти невалидно
2024-01-01T12:00 валидно невалидно (если отсутствуют секунды)

Работа с временными зонами

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

class MeetingDto {
  @IsISO8601()
  scheduledAt: string;
}

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

  • 2024-05-10T10:00:00Z
  • 2024-05-10T10:00:00+05:00
  • 2024-05-10T10:00:00-02:30

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

  • Z эквивалентен UTC+0
  • смещение может быть произвольным в пределах ±23:59
  • наличие временной зоны не является обязательным, если формат даты и времени корректен

Работа с миллисекундами

Поддерживается расширенная точность времени:

2024-05-10T10:00:00.1Z
2024-05-10T10:00:00.123Z
2024-05-10T10:00:00.123456Z

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


Комбинация с другими декораторами

@IsISO8601 часто используется вместе с другими валидаторами для формирования строгих DTO-моделей.

Обязательное поле

import { IsNotEmpty, IsISO8601 } from 'class-validator';

class ReportDto {
  @IsNotEmpty()
  @IsISO8601()
  createdAt: string;
}

Опциональное поле

import { IsOptional, IsISO8601 } from 'class-validator';

class FilterDto {
  @IsOptional()
  @IsISO8601()
  fromDate?: string;
}

В этом случае валидатор @IsISO8601 не срабатывает, если поле отсутствует.


Валидация в сложных структурах

Вложенные объекты

import { Type } from 'class-transformer';
import { ValidateNested, IsISO8601 } from 'class-validator';

class Period {
  @IsISO8601()
  start: string;

  @IsISO8601()
  end: string;
}

class ScheduleDto {
  @ValidateNested()
  @Type(() => Period)
  period: Period;
}

Вложенные структуры требуют использования @ValidateNested, иначе @IsISO8601 внутри не будет применён.


Частые ошибки при использовании

1. Передача объекта Date вместо строки

class WrongDto {
  @IsISO8601()
  date: Date;
}

Проблема заключается в том, что Date автоматически сериализуется в строку, но не всегда в ISO-формат. Это приводит к непредсказуемым результатам.

Правильный подход:

class CorrectDto {
  @IsISO8601()
  date: string;
}

2. Игнорирование временной зоны

2024-01-01T10:00:00

Хотя строка может пройти валидацию, отсутствие временной зоны приводит к неоднозначности при интерпретации времени на сервере и клиенте.


3. Использование нестандартных разделителей

2024.01.01T10:00:00Z
2024-01-01 10:00:00Z

Оба варианта не соответствуют ISO 8601 и будут отклонены.


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

При использовании class-transformer и class-validator в связке важно учитывать порядок преобразования:

  1. plain object → class instance (plainToInstance)
  2. применение декораторов трансформации (@Type)
  3. валидация (validate)

Если строка даты приходит в виде числа или нестандартного формата, @IsISO8601 не выполняет автоматическую конвертацию.


Использование в API-контрактах

@IsISO8601 часто применяется в DTO слоях REST и GraphQL API для обеспечения консистентности входных данных.

Типичный сценарий:

  • клиент отправляет дату как строку
  • сервер проверяет соответствие ISO 8601
  • при успехе значение передаётся в бизнес-логику

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


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

В реальных проектах @IsISO8601 часто комбинируется с другими проверками:

  • диапазоны дат (@MinDate, @MaxDate)
  • логическая проверка интервалов
  • сравнение start < end

Пример:

class RangeDto {
  @IsISO8601()
  start: string;

  @IsISO8601()
  end: string;
}

Дополнительная логика может проверять корректность интервала вне рамок самого декоратора.


Особенности реализации внутри class-validator

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

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

Важно учитывать, что это не полноценный парсер дат, а именно синтаксический валидатор.


Поведение при локализации и форматировании

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

Это исключает ситуации, когда дата интерпретируется по-разному в зависимости от окружения (например, MM/DD/YYYY vs DD/MM/YYYY).


Производительность в массовой валидации

При обработке больших массивов объектов валидатор @IsISO8601 остаётся относительно лёгким по вычислительной нагрузке, так как:

  • выполняется проверка строки
  • не создаются объекты Date
  • не происходит обращение к временным зонам системы

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


Ограничения

Несмотря на строгость, валидатор не решает следующие задачи:

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

Он предназначен исключительно для синтаксической проверки ISO 8601 строки.