Sequelize中如何将DATETIME格式的createdAt、updatedAt转为秒计算时间差,解决结果异常问题
根因定位
- 配置无效:
findAll方法的顶层参数不支持直接声明createdAt/updatedAt类的字段取值规则,代码中写的两行sequelize.literal不会被Sequelize解析执行,完全不起作用。 - 计算逻辑错误:直接对DATETIME类型字段做减法运算时,MySQL会触发隐式类型转换,将时间值转为
20210303224205格式的整数再执行减法,最终结果和真实时间差无关联。按照给定的测试数据计算,20210303224205 - 20210303213058 = 14147,与实际出现的固定14000左右的计算结果完全匹配。 - 格式化参数错误:
date_format方法使用的格式串%Y-%m-%d %H:%m:%S中,%m代表月份,分钟位需要使用%i,否则格式化输出的数值会出现偏差。
正确实现方案
核心逻辑
所有查询字段、计算规则统一放在attributes配置项内,通过数据库原生时间函数实现DATETIME转秒、计算时间差值的需求,避免手动转换触发的隐式类型错误。
完整修正代码
router.get( "/sessions/average_team_time", (req, res) => { models.Session.findAll({ attributes: [ 'id', 'createdAt', 'updatedAt', [Sequelize.fn('time', Sequelize.col('updatedAt')), 'updatedAtHour'], // 修正时间格式化的分钟位参数 [Sequelize.fn('date_format', Sequelize.col('createdAt'), '%Y-%m-%d %H:%i:%S'), 'date_formed'], // 调用TIMESTAMPDIFF直接返回两个时间的秒级差值 [ Sequelize.fn( 'TIMESTAMPDIFF', Sequelize.literal('SECOND'), Sequelize.col('createdAt'), Sequelize.col('updatedAt') ), 'timePlayed' ] ] }) .then((sessions) => res.json(sessions)) .catch((err) => res.json(err)); } );
效果验证
针对给定的测试数据:
createdAt值为2021-03-03 21:30:58updatedAt值为2021-03-03 22:42:05
修正后计算得到的timePlayed为4267秒,完全符合真实时间差,不会出现固定14000的错误结果。
如果偏好使用时间戳转换的实现方式,也可以替换成UNIX_TIMESTAMP函数做计算,最终效果与TIMESTAMPDIFF完全一致:
[ Sequelize.literal('(UNIX_TIMESTAMP(updatedAt) - UNIX_TIMESTAMP(createdAt))'), 'timePlayed' ]
内容的提问来源于stack exchange,提问作者Yahoo
相关产品推荐
相关产品推荐

