You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MomentJS将MongoDB返回日期转为相对日期报Invalid date如何修复

问题修复方案

根因说明

你从Mongoose查询到的是JavaScript原生Date类型对象,Handlebars默认渲染Date类型时会自动调用toString()方法,输出你看到的带本地时区的字符串格式,该格式没有标准化,MomentJS无法直接识别,因此抛出Invalid date错误。

推荐解决方案:注册Handlebars自定义Helper(最稳定)

直接在服务端Handlebars配置中注册日期处理Helper,直接操作原生Date对象,避免不必要的格式转换:

  1. 确认已安装moment依赖
  2. 在Express的Handlebars配置处添加Helper,示例代码如下(以express-handlebars v6+为例):
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');
  1. 在视图模板中直接调用助手即可,无需额外处理日期字段:
<!-- 直接传入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 22:57:03