如何用moment.js获取带详细细分时长的已过去时间?
解决moment.js细分已过去时长的问题
你当前的问题在于直接调用diff()获取的是总时长差值,比如1年2个月的日期,diff('months')会返回14,diff('days')会返回这1年2个月的总天数,所以需要逐步扣除已统计的时长,再计算剩余部分。
可以通过以下步骤修正:
- 创建当前时间的副本,避免修改原moment实例
- 先计算年数,然后把基准时间加上对应的年数,再计算剩余的月数
- 同理,加上月数后计算剩余的天数
- 收集所有非零的时长部分,最后拼接成符合要求的字符串
修正后的代码如下:
function passedTimeMoment(date: number | undefined): string { if (date === undefined) return ''; const now = moment().startOf('day'); const targetDate = moment(date).startOf('day'); const parts: string[] = []; // 计算年数并调整基准时间 const years = now.diff(targetDate, 'years'); if (years > 0) { parts.push(`${years} year${years > 1 ? 's' : ''}`); targetDate.add(years, 'years'); } // 计算剩余月数并调整基准时间 const months = now.diff(targetDate, 'months'); if (months > 0) { parts.push(`${months} month${months > 1 ? 's' : ''}`); targetDate.add(months, 'months'); } // 计算剩余天数 const days = now.diff(targetDate, 'days'); if (days > 0 || parts.length === 0) { // 如果前面都为0,至少显示天数 parts.push(`${days} day${days > 1 ? 's' : ''}`); } // 拼接字符串,处理"and"的位置 if (parts.length === 1) { return `${parts[0]} ago`; } else if (parts.length === 2) { return `${parts[0]} and ${parts[1]} ago`; } else { const lastPart = parts.pop(); return `${parts.join(', ')} and ${lastPart} ago`; } }
关键说明:
- 每次计算完一个时间单位后,用
add()把目标日期往前推进对应的时长,这样后续的diff()只会计算剩余的时间,不会包含已统计的年月部分 - 加入了单复数处理(比如
1 yearvs2 years) - 优化了字符串拼接逻辑,避免出现多余的"and",同时处理了只有单个时间单位的情况
内容的提问来源于stack exchange,提问作者Hasan Parasteh
相关产品推荐
相关产品推荐

