@IsDateString

Декоратор @IsDateString из библиотеки class-validator предназначен для проверки строковых значений, содержащих дату в формате ISO 8601. Проверка выполняется только для строк. Если значение имеет другой тип, валидация завершится ошибкой.

Наиболее частая область применения:

  • DTO в API;
  • валидация входящих JSON-данных;
  • проверка дат в формах;
  • работа с REST и GraphQL;
  • интеграция с NestJS.

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

import { IsDateString } from 'class-validator'

class CreateEventDto {
  @IsDateString()
  startDate: string
}

Корректные значения:

{
  "startDate": "2025-05-10"
}
{
  "startDate": "2025-05-10T12:30:00Z"
}
{
  "startDate": "2025-05-10T12:30:00+03:00"
}

Некорректные значения:

{
  "startDate": "10.05.2025"
}
{
  "startDate": "05/10/2025"
}
{
  "startDate": "random text"
}

Проверка стандарта ISO 8601

@IsDateString использует внутреннюю проверку ISO 8601. Это международный стандарт представления даты и времени.

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

  • дата;
  • дата и время;
  • временная зона;
  • UTC;
  • миллисекунды.

Примеры допустимых форматов:

2025-01-15
2025-01-15T10:20:30Z
2025-01-15T10:20:30+02:00
2025-01-15T10:20:30.000Z

Разница между @IsDateString и @IsDate

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

@IsDateString

Проверяет строку:

@IsDateString()
createdAt: string

Ожидается:

"2025-05-10T12:00:00Z"

@IsDate

Проверяет объект Date:

import { IsDate } from 'class-validator'

class ExampleDto {
  @IsDate()
  createdAt: Date
}

Ожидается:

new Date()

Работа с class-transformer

При работе с HTTP-запросами дата обычно приходит строкой. Поэтому @IsDateString применяется значительно чаще.

Однако иногда требуется преобразование строки в объект Date.

Пример:

import { Type } from 'class-transformer'
import { IsDate } from 'class-validator'

class CreateEventDto {
  @Type(() => Date)
  @IsDate()
  startDate: Date
}

Тогда строка:

{
  "startDate": "2025-05-10T12:00:00Z"
}

будет автоматически преобразована в:

Date

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

import { validate } from 'class-validator'

class UserDto {
  @IsDateString()
  birthday: string
}

async function run() {
  const dto = new UserDto()

  dto.birthday = 'invalid date'

  const errors = await validate(dto)

  console.log(errors)
}

Результат:

[
  ValidationError {
    property: 'birthday',
    constraints: {
      isDateString: 'birthday must be a valid ISO 8601 date string'
    }
  }
]

Пользовательское сообщение об ошибке

import { IsDateString } from 'class-validator'

class ReportDto {
  @IsDateString({
    message: 'Дата должна быть в формате ISO 8601'
  })
  generatedAt: string
}

Проверка обязательного поля

@IsDateString не проверяет наличие значения. Для обязательного поля используется @IsNotEmpty.

import { IsDateString, IsNotEmpty } from 'class-validator'

class BookingDto {
  @IsNotEmpty()
  @IsDateString()
  bookingDate: string
}

Разрешение null и undefined

Для необязательных полей применяется @IsOptional.

import { IsOptional, IsDateString } from 'class-validator'

class UpdateUserDto {
  @IsOptional()
  @IsDateString()
  deletedAt?: string
}

Допустимо:

{}
{
  "deletedAt": "2025-01-01"
}

Недопустимо:

{
  "deletedAt": "tomorrow"
}

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

import { IsArray, IsDateString } from 'class-validator'

class CalendarDto {
  @IsArray()
  @IsDateString({}, { each: true })
  dates: string[]
}

Корректный пример:

{
  "dates": [
    "2025-01-01",
    "2025-02-01"
  ]
}

Параметр strict

Декоратор поддерживает строгий режим проверки.

@IsDateString({ strict: true })
date: string

Строгий режим запрещает невалидные календарные даты.

Например:

2025-02-31

в строгом режиме будет отклонена.


Параметр strictSeparator

Параметр требует обязательного использования символа T между датой и временем.

@IsDateString({
  strictSeparator: true
})
createdAt: string

Допустимо:

2025-01-01T10:00:00Z

Недопустимо:

2025-01-01 10:00:00Z

Полная конфигурация

@IsDateString(
  {
    strict: true,
    strictSeparator: true
  },
  {
    message: 'Некорректная дата'
  }
)
createdAt: string

Использование в NestJS DTO

import { IsDateString } from 'class-validator'

export class CreatePostDto {
  @IsDateString()
  publishedAt: string
}

Пример HTTP-запроса:

POST /posts
Content-Type: application/json
{
  "publishedAt": "2025-05-10T15:00:00Z"
}

Типичные ошибки

Использование типа Date вместе с @IsDateString

Неправильно:

@IsDateString()
createdAt: Date

@IsDateString ожидает строку.

Правильно:

@IsDateString()
createdAt: string

или:

@Type(() => Date)
@IsDate()
createdAt: Date

Нестандартные форматы даты

Неправильно:

31.12.2025
12/31/2025
31-12-2025

Правильно:

2025-12-31

Отсутствие временной зоны

Строка:

2025-01-01T12:00:00

может интерпретироваться по-разному в разных окружениях.

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

2025-01-01T12:00:00Z

Проверка диапазонов дат

@IsDateString проверяет только корректность формата. Для проверки диапазона требуется дополнительная логика.

Пример:

import {
  IsDateString,
  Validate
} from 'class-validator'

class EventDto {
  @IsDateString()
  startDate: string

  @IsDateString()
  endDate: string
}

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

new Date(endDate) > new Date(startDate)

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

Ограничение длины

import {
  IsDateString,
  Length
} from 'class-validator'

class ExampleDto {
  @Length(10, 30)
  @IsDateString()
  date: string
}

Валидация только для определённых сценариев

import {
  IsDateString,
  ValidateIf
} from 'class-validator'

class TaskDto {
  isCompleted: boolean

  @ValidateIf(o => o.isCompleted)
  @IsDateString()
  completedAt?: string
}

Поведение при разных значениях

Значение Результат
"2025-01-01" valid
"2025-01-01T10:00:00Z" valid
"2025-13-01" invalid
"hello" invalid
123 invalid
null invalid
undefined invalid
new Date() invalid

Внутренняя реализация

@IsDateString является сокращением для проверки ISO 8601:

@IsISO8601()

Фактически:

@IsDateString()

эквивалентно:

@IsISO8601()

Поэтому оба декоратора работают одинаково.


Практический пример DTO

import {
  IsDateString,
  IsOptional,
  IsString
} from 'class-validator'

export class CreateMeetingDto {
  @IsString()
  title: string

  @IsDateString({
    strict: true
  })
  startAt: string

  @IsOptional()
  @IsDateString()
  endAt?: string
}

Пример валидного объекта:

{
  "title": "Team Meeting",
  "startAt": "2025-06-01T09:00:00Z",
  "endAt": "2025-06-01T10:00:00Z"
}

Пример невалидного объекта:

{
  "title": "Team Meeting",
  "startAt": "01.06.2025"
}