PSQL posts表DATE字段返回ISO时间 如何格式化为易读日期样式?
问题原因
你遇到的日期格式问题和Express框架无关,本质是两层自动转换导致的:
- PostgreSQL的
DATE类型本身不带时间信息,但JavaScript没有单独的日期类型,所有日期都会被Node.js数据库驱动(通常是pg包)自动转为带时间的原生Date对象,默认取UTC时区的零点 - Express调用
res.json()返回响应时,会自动对Date对象做JSON序列化,默认输出ISO 8601格式,也就是你看到的2021-09-02T07:00:00.000Z样式
解决方案
按需选择以下三类方案即可:
方案1:PostgreSQL查询时直接格式化(推荐后端统一处理场景)
直接在SELECT语句中用to_char函数把日期转为你需要的字符串格式,不需要后续额外处理:
SELECT id, to_char(postingDate, 'FMMonth FMDDth, YYYY') AS postingDate, content FROM posts;
参数说明:
FMMonth:输出完整月份名(如September),前缀FM会去掉字段自动补的空格FMDDth:输出带序数后缀的日期(如2nd、3rd),前缀FM会去掉日期的前导零YYYY:输出4位年份
方案2:Node.js业务层统一处理
如果不想修改SQL语句,可以在拿到数据库查询结果后,统一对postingDate字段做格式化,轻量日期库或原生JS都可以实现:
用date-fns实现(代码更简洁)
首先安装依赖:npm install date-fns
业务层处理逻辑:
const { format } = require('date-fns') // 拿到数据库查询结果后统一处理 const posts = await db.query('SELECT * FROM posts') const formattedPosts = posts.rows.map(post => ({ ...post, postingDate: format(post.postingDate, 'MMMM do, yyyy') })) // 处理完成后再返回给前端 res.json(formattedPosts)
原生JS实现(无额外依赖)
function formatCustomDate(date) { const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] const day = date.getDate() // 计算日期序数后缀 const ordinalSuffix = day % 10 === 1 && day !== 11 ? 'st' : day % 10 === 2 && day !== 12 ? 'nd' : day % 10 === 3 && day !== 13 ? 'rd' : 'th' return `${monthNames[date.getMonth()]} ${day}${ordinalSuffix}, ${date.getFullYear()}` } // 调用方式和上述一致 const formattedPosts = posts.rows.map(post => ({ ...post, postingDate: formatCustomDate(post.postingDate) }))
方案3:前端处理(推荐多端适配场景)
如果后端返回标准ISO格式更便于多端适配,也可以把格式化逻辑放到前端实现,处理逻辑和上述Node.js层的实现完全一致,前端拿到接口响应后再做日期格式化即可。
内容的提问来源于stack exchange,提问作者Brixsta
相关产品推荐
相关产品推荐

