You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 07:54:04