如何在NestJS+Sequelize+PostgreSQL的where子句中正确使用日期参数
问题解决方法
核心错误原因
- 控制器层的
@Query参数默认传入的是字符串类型,仅标注TS类型Date不会自动完成类型转换,NestJS原生不会将2021-09-18这类字符串自动转为Date对象,未转换直接使用就会出现Invalid Date错误 - 服务层查询代码的where子句写法错误,
date: typeof Date是类型判断语法,实际会将date字段的值赋值为function字符串,完全不符合查询需求
正确实现步骤
1. 控制器层添加日期类型转换
推荐使用NestJS官方推荐的class-validator+class-transformer组合实现自动参数校验和转换,先定义查询DTO:
import { Transform } from 'class-transformer'; import { IsDate, IsNotEmpty, IsString } from 'class-validator'; export class ScheduleCountQueryDto { @IsNotEmpty() @Transform(({ value }) => new Date(value)) @IsDate() date: Date; @IsNotEmpty() @IsString() location_schedule: string; }
修改控制器代码绑定DTO:
@Get('count') async countAllForDateAndLocation(@Query() query: ScheduleCountQueryDto) { return this.scheduleService.countAllForDateAndLocation(query.date, query.location_schedule); }
如果不想引入DTO,也可以在控制器内手动转换并校验:
@Get('count') async countAllForDateAndLocation(@Query('date') dateStr: string, @Query('location_schedule') location_schedule: string) { const date = new Date(dateStr); if (isNaN(date.getTime())) { throw new BadRequestException('无效的日期格式'); } return this.scheduleService.countAllForDateAndLocation(date, location_schedule); }
2. 修正服务层查询代码
import { Op } from 'sequelize'; // 需先导入sequelize的操作符 async countAllForDateAndLocation(date: Date, location_schedule: string) { // 如果需要查询指定日期全天的数据,建议加时间范围查询,避免时区问题导致数据遗漏 const startOfDay = new Date(date.setHours(0, 0, 0, 0)); const endOfDay = new Date(date.setHours(23, 59, 59, 999)); return Schedule.findAll({ where: { date: { [Op.between]: [startOfDay, endOfDay] }, location_schedule: location_schedule, } }) }
注意:如果PostgreSQL中
date字段的类型是date而非timestamp with time zone,可以直接传入转换后的date对象即可,不需要范围查询。
内容的提问来源于stack exchange,提问作者Rodrigo Bernardes
相关产品推荐
相关产品推荐

