我正在使用带有类验证器的Nest,并试图验证UI提供的日期不早于今天使用@isDateString()
和@MinDate()
export class SchemaDto {
@IsOptional()
@IsDateString()
@MinDate(new Date())
myDate?: Date;
}
我发送进来的数据是一个带有以下日期的Date对象:
Mon Oct 04 2021 00:00:00 GMT-0400 (Eastern Daylight Time)
我从类验证器得到的错误是:
minimal allowed date for myDate is Fri Oct 01 2021 15:57:18 GMT-0400 (Eastern Daylight Time)
问题:
如果我删除minDate装饰器,一切都可以正常工作,但我宁愿验证这个常见的情况。
信息:打印稿:~ 4.1.4
节点:12.4.0
class-validator: 0.13.1
巢:7.0.0
验证与@MinDate
export class SchemaDto {
@IsNotEmpty()
@Transform( ({ value }) => new Date(value))
@IsDate()
@MinDate(new Date())
myDate: Date;
}
但是如果value是可选的,它可能是null或undefined,所以:
export class SchemaDto {
@IsOptional()
@Transform( ({ value }) => value && new Date(value))
@IsDate()
@MinDate(new Date())
myDate?: Date;
}
海安回答中的@Transform
方法有效,因为它省略了OP问题中包含的@IsDateString
装饰器。如果您打算保留@IsDateString
装饰器,那么当您将其与@Transform
装饰器(@Transform( ({ value }) => new Date(value))
)一起使用时,您将遇到新的错误。
使用@IsDateString
意味着您希望使用ISO8601格式的日期字符串作为输入。问题是@MinDate
接受Date
类型的参数,而在您的情况下,在运行时传递给它的是字符串。查看MinDate的验证器实现可以发现,如果装饰属性的值不是Date
的实例,验证将失败。使用@Transform
装饰器将日期字符串转换为日期对象仍然是@IsDateString
的一个问题,因为您会得到一个错误,即接收到的输入不是有效的ISO8601日期字符串。这是因为转换发生在应用装饰器之前。好消息是,在GitHub的typestack/class-validator repo中,有一个带有PR的问题,可以修复同时使用@IsDateString
和@MinDate
验证器所带来的冲突——但它看起来不会很快被合并。
解决方案吗?我建议您实现一个自定义装饰器。您可以将装饰器的名称保留为MinDate,这样,当合并/发布指定动态日期PR的功能:Make MinDate和maxDate支持时,您只需要更新类验证器版本并更改MinDate导入路径。下面是我的实现使一行改变最初的实现允许MinDate收到一个日期字符串:
custom-min-date.decorator.ts
import { buildMessage, ValidateBy, ValidationOptions } from 'class-validator';
export const MIN_DATE = 'minDate';
/**
* Checks if the value is a date that's after the specified date.
*/
export function minDate(date: unknown, minDate: Date): boolean {
const dateObject: Date = typeof date === 'string' ? new Date(date) : <Date>date;
return dateObject instanceof Date && dateObject.getTime() >= minDate.getTime();
}
/**
* Checks if the value is a date that's after the specified date.
*/
export function MinDate(date: Date, validationOptions?: ValidationOptions): PropertyDecorator {
return ValidateBy(
{
name: MIN_DATE,
constraints: [date],
validator: {
validate: (value, args): boolean => minDate(value, args.constraints[0]),
defaultMessage: buildMessage(
(eachPrefix) => 'minimal allowed date for ' + eachPrefix + '$property is $constraint1',
validationOptions,
),
},
},
validationOptions,
);
}
我希望这能帮助到别人。
你可以用IsDateString()代替你的IsDate(),它会为你做转换