kakasoo

class-validator로 특정 날짜 검증하기 본문

프로그래밍/NestJS

class-validator로 특정 날짜 검증하기

카카수(kakasoo) 2023. 1. 1. 12:02
반응형
@IsDate()
specificDate: Date;

날짜를 검증하기 위해서는 IsDate 데코레이터를 이용할 수 있다.

이렇게 작성할 경우 단순 String으로 된 Date는 무시당할 수 있기 때문에 Type 데코레이터도 필요하다.

날짜가 필수적인지 아닌지에 따라 아래와 같이 작성할 수 있다.

import { applyDecorators } from '@nestjs/common';
import { Type } from 'class-transformer';
import { IsDate, IsNotEmpty } from 'class-validator';

export function IsNotEmptyDate() {
    return applyDecorators(
        IsNotEmpty(),
        IsDate(),
        Type(() => Date),
    );
}
import { applyDecorators } from '@nestjs/common';
import { Type } from 'class-transformer';
import { IsDate, IsOptional } from 'class-validator';

export function IsOptionalDate() {
    return applyDecorators(
        IsOptional(),
        IsDate(),
        Type(() => Date),
    );
}

위는 필수적인 케이스고, 아래는 선택적인 케이스를 작성한 것이다.

이를 합쳐서 아래와 같이 인자를 받는 형태로 작성할 수 있다.

export function IsDateDecorator(isOptional: boolean = true) {
    return applyDecorators(
        isOptional ? IsOptional() : IsNotEmpty(),
        IsDate(),
        Type(() => Date),
    );
}

하지만 날짜의 입력은, 서비스 특성에 따라 오늘 날짜를 포함한 시간대 이후를 받아야 할 수도 있다.

또한 시간 단위가 아니라 날짜 단위, 예컨대 23:59과 00:00를 1분 차이가 아니라 하루 차이로 볼 수도 있다.

이런 경우를 위해 아래와 같이 데코레이터를 만들 수 있다.

IsAfterDate decorator

import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator';

export function getDifferTime(a: Date, b: Date, standard: 'day' | 'hour') {
    if (standard === 'day') {
        return a.getDate() - b.getDate();
    } else if (standard === 'hour') {
        const differTime = a.getTime() - b.getTime();
        return differTime / (1000 * 60 * 60);
    }
}

export function IsAfterDate(validationOptions?: { hours: number } & ValidationOptions) {
    return function (object: Record<string, any>, propertyName: string) {
        registerDecorator({
            name: 'IsAfterDate',
            target: object.constructor,
            propertyName: propertyName,
            options: validationOptions,
            constraints: [],
            validator: {
                validate(value: any, args: ValidationArguments) {
                    return value instanceof Date && getDifferTime(value, new Date(), 'hour') >= validationOptions.hours;
                },
            },
        });
    };
}

class-validator는 registerDecorator 를 통해 손쉽게 커스텀 데코레이터를 만들 수 있다.

위의 applyDecorator는 기존의 데코레이터를 합성하는 방식이지만,

registerDecorator는 기존에 없던 데코레이터를 만들 수 있기에 더 기능 확장에 용이하다.

반응형