如何用Moment.js或纯JS实现多维度分区间的帖子相对时间展示
基于Moment.js的修改实现
直接替换原有fromNow()的单维度输出逻辑,自定义多维度时间差生成规则,完全覆盖需求场景:
核心逻辑说明
- 特殊场景优先判断:间隔小于1分钟输出
Just Now,当日发布输出Today,不会出现空值 - 非当日场景按年、月、周、天的优先级拆分非零时间单位
- 自动适配单复数规则,用逗号拼接多个时间单位后加
ago后缀
修改后的完整可运行代码
$(document).ready(function () { var publishedDate = ".iso-date"; var displayDate = ".display-date"; $(publishedDate).each(function (i, e) { const rawDate = $(e).text().trim(); const $target = $(e).next(displayDate); const publishedMoment = moment(rawDate); // 跳过无效日期 if (!publishedMoment.isValid()) return; const now = moment(); let outputText = ""; // 特殊场景处理 if (now.diff(publishedMoment, 'minutes') < 1) { outputText = "Just Now"; } else if (now.isSame(publishedMoment, 'day')) { outputText = "Today"; } else { // 拆分多维度时间差 const duration = moment.duration(now.diff(publishedMoment)); const timeUnits = []; // 按优先级从高到低取非零单位 const years = duration.years(); if (years) timeUnits.push(`${years} ${years === 1 ? 'year' : 'years'}`); const months = duration.months(); if (months) timeUnits.push(`${months} ${months === 1 ? 'month' : 'months'}`); const weeks = duration.weeks(); if (weeks) timeUnits.push(`${weeks} ${weeks === 1 ? 'week' : 'weeks'}`); const days = duration.days(); if (days) timeUnits.push(`${days} ${days === 1 ? 'day' : 'days'}`); outputText = timeUnits.join(', ') + ' ago'; } $target.text(`Posted ${outputText}`); }); });
可选精简配置
如果不需要展示所有层级的时间单位,只展示最高优先级的1-2个区间,只需在timeUnits生成后添加截取逻辑即可:
// 仅保留优先级最高的2个时间单位 if (timeUnits.length > 2) timeUnits.length = 2; outputText = timeUnits.join(', ') + ' ago';
无额外依赖的纯JavaScript实现
无需引入Moment.js、jQuery等第三方库,用原生API即可实现同等效果:
实现代码
document.addEventListener('DOMContentLoaded', function () { const publishedDateEls = document.querySelectorAll('.iso-date'); const displayDateSelector = '.display-date'; publishedDateEls.forEach(el => { const rawDate = el.textContent.trim(); const targetEl = el.nextElementSibling; // 校验相邻元素是否为目标输出节点 if (!targetEl || !targetEl.matches(displayDateSelector)) return; const publishedTime = new Date(rawDate).getTime(); // 跳过无效日期 if (isNaN(publishedTime)) return; const now = new Date(); const nowTime = now.getTime(); let outputText = ''; const diffMs = nowTime - publishedTime; const diffMinutes = Math.floor(diffMs / (1000 * 60)); // 特殊场景处理 if (diffMinutes < 1) { outputText = 'Just Now'; } else { const publishedDateObj = new Date(publishedTime); // 校验是否为同一自然日 const isSameDay = now.getFullYear() === publishedDateObj.getFullYear() && now.getMonth() === publishedDateObj.getMonth() && now.getDate() === publishedDateObj.getDate(); if (isSameDay) { outputText = 'Today'; } else { const timeUnits = []; // 计算年差,修正未到发布月的情况 let years = now.getFullYear() - publishedDateObj.getFullYear(); if (now.getMonth() < publishedDateObj.getMonth() || (now.getMonth() === publishedDateObj.getMonth() && now.getDate() < publishedDateObj.getDate())) { years--; } if (years > 0) timeUnits.push(`${years} ${years === 1 ? 'year' : 'years'}`); // 计算剩余月差 let totalMonths = (now.getFullYear() - publishedDateObj.getFullYear()) * 12 + now.getMonth() - publishedDateObj.getMonth(); if (now.getDate() < publishedDateObj.getDate()) totalMonths--; const months = totalMonths % 12; if (months > 0) timeUnits.push(`${months} ${months === 1 ? 'month' : 'months'}`); // 计算剩余天、周差 const totalDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); const remainDays = totalDays - years * 365 - months * 30; const weeks = Math.floor(remainDays / 7); const days = remainDays % 7; if (weeks > 0) timeUnits.push(`${weeks} ${weeks === 1 ? 'week' : 'weeks'}`); if (days > 0) timeUnits.push(`${days} ${days === 1 ? 'day' : 'days'}`); outputText = timeUnits.join(', ') + ' ago'; } } targetEl.textContent = `Posted ${outputText}`; }); });
精度说明
原生实现的年、月、天拆分采用近似规则(年按365天、月按30天计算),满足绝大多数内容展示场景;如果需要和日历完全对齐的精确差值,可自行调整年、月的修正逻辑。
内容的提问来源于stack exchange,提问作者glennyboy
相关产品推荐
相关产品推荐

