Декоратор @MinDate проверяет, что значение даты не
меньше указанного минимального значения. Проверка применяется к объектам
Date и используется для ограничения диапазона допустимых
дат.
Наиболее распространённые сценарии:
import { MinDate } from 'class-validator'
class EventDto {
@MinDate(new Date())
eventDate: Date
}
В этом примере поле eventDate должно содержать дату не
раньше текущего момента.
Если передать дату из прошлого, валидация завершится ошибкой.
@MinDate сравнивает значение поля с указанной датой:
value >= minDate
Если условие истинно — валидация проходит успешно.
import { validate } from 'class-validator'
import { MinDate } from 'class-validator'
class UserDto {
@MinDate(new Date('2025-01-01'))
registrationDate: Date
}
async function run() {
const dto = new UserDto()
dto.registrationDate = new Date('2024-05-10')
const errors = await validate(dto)
console.log(errors)
}
run()
Ошибка возникнет потому, что дата меньше установленного ограничения.
Одна из самых популярных задач — запрет дат в прошлом.
class BookingDto {
@MinDate(new Date())
bookingDate: Date
}
Такой подход имеет важную особенность.
@MinDate(new Date())
new Date() вызывается в момент создания класса, а не во
время валидации.
Это означает, что минимальная дата фиксируется один раз.
Например:
class ExampleDto {
@MinDate(new Date())
date: Date
}
Если сервер работает несколько суток без перезапуска, минимальная дата останется старой.
Для динамических значений используется функция.
class BookingDto {
@MinDate(() => new Date())
bookingDate: Date
}
Теперь дата вычисляется во время каждой проверки.
Это правильный способ проверки текущего времени.
class PersonDto {
@MinDate(new Date('1900-01-01'))
birthDate: Date
}
Подобная проверка предотвращает ввод некорректно старых дат.
@IsDate@MinDate не проверяет тип значения. Декоратор лишь
сравнивает даты.
Поэтому обычно используется комбинация:
import {
IsDate,
MinDate
} from 'class-validator'
class TaskDto {
@IsDate()
@MinDate(() => new Date())
deadline: Date
}
Частая ошибка — передача строк вместо объектов Date.
dto.deadline = '2026-01-01'
@IsDate() не пропустит такое значение.
При использовании class-transformer можно автоматически
преобразовывать строки.
import { Type } from 'class-transformer'
import { IsDate, MinDate } from 'class-validator'
class EventDto {
@Type(() => Date)
@IsDate()
@MinDate(() => new Date())
date: Date
}
Теперь строка:
{
"date": "2026-10-01"
}
будет преобразована в объект Date.
class ConferenceDto {
@Type(() => Date)
@IsDate()
@MinDate(() => new Date())
startDate: Date
}
Такой подход часто используется в:
class BookingDto {
@MinDate(() => new Date(), {
message: 'Дата бронирования не может быть в прошлом'
})
bookingDate: Date
}
class PaymentDto {
@MinDate(() => new Date(), {
message: (args) => {
return `Дата ${args.value} недопустима`
}
})
paymentDate: Date
}
class SubscriptionDto {
@Type(() => Date)
@IsDate()
@MinDate(() => new Date())
startDate: Date
@Type(() => Date)
@IsDate()
@MinDate(() => new Date())
renewalDate: Date
}
Если поле необязательно, применяется @IsOptional.
import {
IsOptional,
IsDate,
MinDate
} from 'class-validator'
class UpdateDto {
@IsOptional()
@IsDate()
@MinDate(() => new Date())
publishDate?: Date
}
nulldto.publishDate = null
Если отсутствует @IsOptional(), валидация завершится
ошибкой.
DTO:
import {
IsDate,
MinDate
} from 'class-validator'
import { Type } from 'class-transformer'
export class CreateEventDto {
@Type(() => Date)
@IsDate()
@MinDate(() => new Date())
eventDate: Date
}
Контроллер:
@Post()
create(@Body() dto: CreateEventDto) {
return dto
}
Пример ответа:
{
"statusCode": 400,
"message": [
"eventDate минимально допустимая дата ..."
],
"error": "Bad Request"
}
@MaxDate@MaxDate выполняет противоположную задачу — проверяет,
что дата не превышает установленный максимум.
Условие проверки:
value <= maxDate
import { MaxDate } from 'class-validator'
class ArchiveDto {
@MaxDate(new Date())
archivedAt: Date
}
Поле не может содержать дату из будущего.
Один из самых частых сценариев:
class UserDto {
@MaxDate(new Date())
birthDate: Date
}
Дата рождения не должна быть больше текущей даты.
Как и в случае с @MinDate, рекомендуется использовать
функцию.
class UserDto {
@MaxDate(() => new Date())
birthDate: Date
}
class ReportDto {
@MaxDate(new Date('2030-01-01'))
reportDate: Date
}
class HistoryDto {
@Type(() => Date)
@IsDate()
@MaxDate(() => new Date())
eventDate: Date
}
Такой подход предотвращает появление будущих событий в архиве.
@MinDate и
@MaxDateОба декоратора часто используются вместе.
class VacationDto {
@Type(() => Date)
@IsDate()
@MinDate(new Date('2025-01-01'))
@MaxDate(new Date('2025-12-31'))
vacationDate: Date
}
Теперь допустимы только даты внутри 2025 года.
class SeasonDto {
@Type(() => Date)
@IsDate()
@MinDate(new Date('2025-06-01'))
@MaxDate(new Date('2025-08-31'))
date: Date
}
class TaskDto {
@Type(() => Date)
@IsDate()
@MinDate(() => new Date())
@MaxDate(new Date('2030-01-01'))
deadline: Date
}
Здесь:
class UploadDto {
@MaxDate(() => new Date(), {
message: 'Дата загрузки не может быть из будущего'
})
uploadedAt: Date
}
Date в JavaScript хранит время в UTC.
Это может приводить к неожиданным результатам:
new Date('2025-01-01')
может интерпретироваться по-разному в зависимости от часового пояса.
@MaxDate(new Date('2025-01-01'))
Если приложение работает в разных регионах, сравнение дат может давать неожиданные результаты около полуночи.
new Date('2025-01-01T00:00:00Z')
new Date(Date.UTC(2025, 0, 1))
Иногда необходимо обнулять часы:
const date = new Date()
date.setHours(0, 0, 0, 0)
@MinDate и @MaxDate сравнивают полные
timestamp-значения.
Это означает:
2025-01-01 10:00
и
2025-01-01 20:00
— разные значения.
function normalizeDate(date: Date) {
const result = new Date(date)
result.setHours(0, 0, 0, 0)
return result
}
Использование:
class ExampleDto {
@MinDate(normalizeDate(new Date()))
date: Date
}
import {
IsArray,
IsDate,
MinDate
} from 'class-validator'
class CalendarDto {
@IsArray()
@IsDate({ each: true })
@MinDate(() => new Date(), {
each: true
})
dates: Date[]
}
class ScheduleDto {
@IsArray()
@Type(() => Date)
@IsDate({ each: true })
@MinDate(() => new Date(), {
each: true
})
events: Date[]
}
import {
ValidateNested,
IsDate,
MinDate
} from 'class-validator'
import { Type } from 'class-transformer'
class EventItemDto {
@Type(() => Date)
@IsDate()
@MinDate(() => new Date())
date: Date
}
class CalendarDto {
@ValidateNested({ each: true })
@Type(() => EventItemDto)
items: EventItemDto[]
}
class PublishDto {
@MinDate(() => new Date(), {
groups: ['create']
})
publishDate: Date
}
Проверка:
validate(dto, {
groups: ['create']
})
import {
ValidateIf,
MinDate
} from 'class-validator'
class EventDto {
isPublished: boolean
@ValidateIf(o => o.isPublished)
@MinDate(() => new Date())
publishDate: Date
}
DatepublishDate: '2025-01-01'
@Type(() => Date)Без трансформации строки не превращаются в объекты даты.
new Date() без функции@MinDate(new Date())
Фиксирует дату при старте приложения.
Особенно критично для международных систем.
@MinDate и @MaxDate всегда учитывают
время.
import {
IsDate,
MinDate,
MaxDate,
IsOptional
} from 'class-validator'
import { Type } from 'class-transformer'
export class CreateWebinarDto {
@Type(() => Date)
@IsDate()
@MinDate(() => new Date(), {
message: 'Дата начала не может быть в прошлом'
})
startDate: Date
@Type(() => Date)
@IsDate()
@MaxDate(new Date('2035-01-01'), {
message: 'Дата окончания слишком большая'
})
endDate: Date
@IsOptional()
@Type(() => Date)
@IsDate()
@MaxDate(() => new Date())
createdAt?: Date
}