Sequelize关联查询Posts与Likes表时如何格式化createdAt日期字段
Sequelize 自定义格式化 createdAt 等 datetime 字段方案
你当前使用 NodeJS + Express + Sequelize + MySQL 技术栈,Posts 表通过 hasMany 关联 Likes 表,查询帖子列表时需要对返回结果中的时间字段做自定义格式化,以下是三种可直接落地的实现方式,可根据项目需求选择:
方案1:全局统一配置(所有模型生效,复用性最高)
如果项目中所有表的时间字段都需要统一格式,直接在 Sequelize 初始化实例时添加配置即可,一次配置全局生效,关联查询出的Likes表时间字段也会自动格式化。
// 初始化sequelize的配置文件 const { Sequelize } = require('sequelize'); const dayjs = require('dayjs'); // 轻量时间处理库,需提前执行 npm i dayjs 安装 const sequelize = new Sequelize('你的数据库名', '数据库账号', '数据库密码', { host: 'localhost', dialect: 'mysql', timezone: '+08:00', // 国内场景配置东八区,避免时间和本地差8小时 define: { timestamps: true, // 全局时间字段getter,统一格式化输出 getterMethods: { createdAt() { const rawTime = this.getDataValue('createdAt'); // 可自定义修改格式,比如要YYYY/MM/DD就改format参数 return rawTime ? dayjs(rawTime).format('YYYY-MM-DD HH:mm:ss') : null; }, updatedAt() { const rawTime = this.getDataValue('updatedAt'); return rawTime ? dayjs(rawTime).format('YYYY-MM-DD HH:mm:ss') : null; } } } });
方案2:单模型独立配置(仅指定表生效)
如果不需要全局修改,只需要给Posts、Likes等特定表的时间字段做格式化,直接在对应模型定义中添加字段 getter 即可,以你现有Posts模型为例,修改后代码如下:
const dayjs = require('dayjs'); module.exports = (sequelize, DataTypes) => { const Posts = sequelize.define("Posts", { title: { type: DataTypes.STRING, allowNull: false, }, postText: { type: DataTypes.STRING, allowNull: false, }, username: { type: DataTypes.STRING, allowNull: false, }, // 单独给createdAt配置格式化规则 createdAt: { type: DataTypes.DATE, get() { const rawValue = this.getDataValue('createdAt'); return rawValue ? dayjs(rawValue).format('YYYY-MM-DD HH:mm:ss') : null; } }, updatedAt: { type: DataTypes.DATE, get() { const rawValue = this.getDataValue('updatedAt'); return rawValue ? dayjs(rawValue).format('YYYY-MM-DD HH:mm:ss') : null; } } }); Posts.associate = (models) => { Posts.hasMany(models.Comments, { onDelete: "cascade", }); Posts.hasMany(models.Likes, { onDelete: "cascade", }); }; return Posts; };
Likes模型的时间格式化按相同逻辑添加配置即可,关联查询时会自动应用格式化规则。
方案3:查询结果遍历处理(单次接口定制,灵活度最高)
如果不想修改全局或模型配置,仅当前帖子列表接口需要特殊时间格式,直接在查询拿到结果后遍历处理字段即可,修改你现有接口代码如下:
const dayjs = require('dayjs'); router.get("/", validateToken, async (req, res) => { const listOfPosts = await Posts.findAll({ include: [Likes], order: [["createdAt", "desc"]], }); // 格式化帖子及关联点赞数据的时间字段 const formattedPosts = listOfPosts.map(post => { const postData = post.toJSON(); // Sequelize实例转普通对象才可修改属性 postData.createdAt = dayjs(postData.createdAt).format('YYYY-MM-DD HH:mm:ss'); postData.updatedAt = dayjs(postData.updatedAt).format('YYYY-MM-DD HH:mm:ss'); // 处理关联的Likes记录时间 postData.Likes = postData.Likes.map(like => { like.createdAt = dayjs(like.createdAt).format('YYYY-MM-DD HH:mm:ss'); like.updatedAt = dayjs(like.updatedAt).format('YYYY-MM-DD HH:mm:ss'); return like; }) return postData; }) const likedPosts = await Likes.findAll({ where: { UserId: req.user.id } }); // 格式化当前用户点赞记录的时间 const formattedLikedPosts = likedPosts.map(like => { const likeData = like.toJSON(); likeData.createdAt = dayjs(likeData.createdAt).format('YYYY-MM-DD HH:mm:ss'); likeData.updatedAt = dayjs(likeData.updatedAt).format('YYYY-MM-DD HH:mm:ss'); return likeData; }) res.json({ listOfPosts: formattedPosts, likedPosts: formattedLikedPosts }); });
补充说明
- 若不想引入dayjs依赖,可使用原生
Date对象的toLocaleString方法实现基础格式化:new Date(rawTime).toLocaleString('zh-CN', {timeZone: 'Asia/Shanghai'}),但自定义格式的灵活度较低。 - 必须配置对应时区,否则Sequelize默认使用UTC时间,国内场景下返回的时间会比实际时间早8小时。
内容的提问来源于stack exchange,提问作者M7md-Dev
相关产品推荐
相关产品推荐

