
本文详解 Moment.js 中 fromNow() 方法因时间格式解析不全导致“18小时前”等错误相对时间显示的问题,重点说明日期时间字符串需严格匹配解析格式(如补充 H:i:s),并提供 Laravel + Vue/Blade 环境下的完整修复方案。
本文详解 moment.js 中 fromnow() 方法因时间格式解析不全导致“18小时前”等错误相对时间显示的问题,重点说明日期时间字符串需严格匹配解析格式(如补充 `h:i:s`),并提供 laravel + vue/blade 环境下的完整修复方案。
在使用 Moment.js 的 fromNow() 方法将服务器返回的时间戳转换为“刚刚”“2小时前”等人类可读的相对时间时,一个常见却极易被忽视的错误是:解析格式(format string)与实际数据格式不一致。正如本例所示,原始代码中:
let criado = moment(data, "DD/MM/YYYY").fromNow();
仅指定了日期部分 "DD/MM/YYYY",但后端传递的 oData.created_at 实际值为 17-08-2022 15:46:29(含时分秒)。Moment.js 在格式不匹配时会默认将时分秒设为 00:00:00,导致解析出的时间比真实时间早约 15 小时——因此本应显示“刚刚”或“几分钟前”,却错误显示为“18小时前”。
✅ 正确做法是完整声明输入字符串的格式,包括时、分、秒及分隔符。由于 PHP 模型中返回的是 d-m-Y H:i:s 格式(注意:Laravel 中 date("d-m-Y H:i:s", ...) 生成的是短横线 - 分隔的日期),而 Moment.js 格式符中 / 表示斜杠,需同步调整:
fnCreatedCell: function (nTd, sData, oData, iRow, iCol) {
moment.locale('pt-br'); // 设置葡萄牙语本地化
const data = oData.created_at; // 例如:"17-08-2022 15:46:29"
// ✅ 关键修复:格式字符串必须与实际数据完全一致(此处为短横线+空格+冒号)
const criado = moment(data, "DD-MM-YYYY HH:mm:ss").fromNow();
$(nTd).html(criado);
}
⚠️ 注意事项:
-
格式符大小写敏感:
HH表示24小时制(00–23),hh表示12小时制;mm是分钟,MM是月份——混淆会导致解析失败或偏差。 -
分隔符需精确匹配:PHP 输出用
-(d-m-Y),则 Moment 格式中必须用-,不可写成/或.。 -
服务端时间一致性:确保 Laravel 返回的时间为应用所在时区(如
Asia/Shanghai),避免因服务器时区与用户浏览器时区差异引入额外偏移。 -
推荐升级方案:Moment.js 已进入维护模式,建议新项目改用 Luxon 或 date-fns。若仍用 Moment,可考虑配合
moment-timezone处理多时区场景。
总结:fromNow() 的准确性完全依赖于 moment(String, String) 构造函数中第二个参数(格式字符串)的严谨性。一次漏掉 HH:mm:ss,就可能导致数小时的语义偏差。开发中务必校验后端输出的实际字符串格式,并在 Moment 解析时逐字符对齐——这是实现精准相对时间显示的基石。











