PostgreSQL插入无时区时间值报错,如何正确存储仅时间部分?
解决PostgreSQL time字段插入失败问题
问题原因
JavaScript的Date对象本质是包含日期的时间戳,当你用new Date('12:22:00')创建实例时,它会自动拼接当前日期生成完整的时间戳。而从你的代码判断使用的MikroORM在将这类Date对象映射到PostgreSQL的time字段时,驱动无法正确提取纯时间部分,导致抛出"Invalid time value"错误。pgAdmin能直接成功是因为它接受纯字符串格式的时间值。
解决方案
方案1:直接传入字符串格式的时间值
既然PostgreSQL的time类型原生支持HH:MM:SS格式的字符串,直接将时间以字符串形式传入即可,无需通过Date对象转换:
// 实体定义保持不变 @Property({ type: 'time' }) startTime!: Date; // 服务函数中直接传时间字符串 await this.persistAndFlush(context, shiftType, { name: input.name, startTime: '12:22:00', endTime: '12:22:00', status: activeStatus, });
MikroORM会自动将字符串映射到PostgreSQL的time字段,读取时也会转换为Date对象(日期部分为当前日期,仅时间部分有效)。
方案2:自定义类型处理时间转换
如果希望代码中始终使用Date对象操作,可以自定义一个MikroORM类型,自动处理Date与PostgreSQLtime字段的转换:
import { Type, ConversionError } from '@mikro-orm/core'; export class TimeType extends Type { // 将JS值转换为数据库可接受的格式 convertToDatabaseValue(value: Date | string): string { if (value instanceof Date) { // 提取HH:MM:SS格式的时间字符串 return value.toTimeString().split(' ')[0]; } if (typeof value === 'string') { return value; } throw new ConversionError(`Invalid time value: ${value}`); } // 将数据库值转换为JS的Date对象 convertToJSValue(value: string): Date { const date = new Date(); const [hours, minutes, seconds] = value.split(':').map(Number); date.setHours(hours, minutes, seconds, 0); return date; } // 指定数据库字段类型 getColumnType() { return 'time'; } }
然后在实体中使用这个自定义类型:
@Property({ type: TimeType }) startTime!: Date;
这样无论你传入Date对象还是时间字符串,都能正确映射到PostgreSQL的time字段。
内容的提问来源于stack exchange,提问作者Athulya Ratheesh
相关产品推荐
相关产品推荐

