使用MomentJS将MongoDB返回日期转为相对日期报Invalid date如何修复
问题修复方案
根因说明
你从Mongoose查询到的是JavaScript原生Date类型对象,Handlebars默认渲染Date类型时会自动调用toString()方法,输出你看到的带本地时区的字符串格式,该格式没有标准化,MomentJS无法直接识别,因此抛出Invalid date错误。
推荐解决方案:注册Handlebars自定义Helper(最稳定)
直接在服务端Handlebars配置中注册日期处理Helper,直接操作原生Date对象,避免不必要的格式转换:
- 确认已安装
moment依赖 - 在Express的Handlebars配置处添加Helper,示例代码如下(以
express-handlebarsv6+为例):
const moment = require('moment'); const exphbs = require('express-handlebars'); // 配置handlebars引擎 app.engine('hbs', exphbs.engine({ extname: '.hbs', // 注册自定义助手 helpers: { // 相对日期转换助手 relativeDate: function (rawDate) { // 直接传入原生Date对象,Moment可直接识别 return moment(rawDate).fromNow(); } } })); app.set('view engine', 'hbs');
- 在视图模板中直接调用助手即可,无需额外处理日期字段:
<!-- 直接传入Mongoose返回的日期字段即可 --> 发布时间:{{relativeDate createdAt}}
备选方案1:提前将日期转为标准ISO字符串传递给模板
如果不想注册Helper,可在路由查询数据后,先把日期字段转为标准ISO字符串再传入模板:
// 示例路由逻辑 async function postList (req, res) { // 查询数据时加lean()获得普通JS对象,方便修改 const posts = await Post.find().lean(); // 处理日期字段 const processedPosts = posts.map(post => ({ ...post, createdAt: post.createdAt.toISOString() })); res.render('post-list', { posts: processedPosts }); }
后续不管是服务端渲染还是前端调用Moment处理该ISO字符串,都不会出现识别错误。
备选方案2:前端指定格式解析(不推荐)
如果你是在前端调用Moment处理渲染后的日期字符串,可以手动指定解析格式适配本地toString的输出:
const dateStr = 'Sun Aug 15 2021 20:44:02 GMT+0700 (Western Indonesia Time)'; // 手动匹配格式解析 const relativeDate = moment(dateStr, 'EEE MMM DD YYYY HH:mm:ss [GMT]ZZ').fromNow();
该方案稳定性差,服务端时区变更会直接导致解析失败,仅做临时修复参考。
内容的提问来源于stack exchange,提问作者Zan
相关产品推荐
相关产品推荐

