使用Moment.js计算两选定日期覆盖的所有自然月总天数
原代码核心缺陷
- 逻辑覆盖不全:仅提取两个输入日期对应月份的天数做简单累加,完全没有设置遍历两个日期跨域区间内所有自然月的流程,只要两个日期之间间隔了整月,就会直接漏算中间月份的天数。
- 判断逻辑无效:通过两个月份的天数差值判断是否属于同月,这个逻辑本身不成立——比如1月和3月的整月天数都是31天,差值为0,原代码会直接只返回单月的31天,连首尾两个月的累加都做不到,进一步放大了计算错误。
- 存在无效冗余:代码中夹带了打印当前实时日期天数的调试语句,和实际计算逻辑没有关联。
正确实现方案
核心实现逻辑:
- 对两个输入日期做归一化处理:统一对齐到当月1号的时间点,彻底消除“具体是当月几号”对月份范围判断的干扰
- 自动识别两个月份的先后顺序,避免用户传入日期顺序颠倒时计算出错
- 从最早的月份开始,逐月向后遍历直到最晚的月份,每遍历一个月就取当月整月天数做累加
实现代码:
const getTotalDaysOfCoveredMonths = (selectedDate1, selectedDate2) => { // 归一化两个日期到当月1号的时间点,消除具体日的干扰 const monthOfFirst = moment(selectedDate1).startOf('month') const monthOfSecond = moment(selectedDate2).startOf('month') // 自动校正日期顺序,兼容用户传入参数颠倒的场景 const [startMonth, endMonth] = monthOfFirst.unix() <= monthOfSecond.unix() ? [monthOfFirst, monthOfSecond] : [monthOfSecond, monthOfFirst] let totalDays = 0 let cursor = startMonth.clone() // 逐月遍历所有覆盖的自然月 while (cursor.unix() <= endMonth.unix()) { totalDays += cursor.daysInMonth() // 游标向后移动一个月 cursor.add(1, 'month') } return totalDays }
场景验证
- 题目示例测试:输入
2021-01-01、2021-03-01,遍历覆盖1月、2月、3月,累加结果为31 + 28 + 31 = 90,完全符合需求预期 - 同月场景测试:输入同月份的两个任意日期,自动返回对应自然月的整月天数,不会重复计算
- 跨多年场景测试:比如从2020年12月到2021年2月,会自动遍历3个月份,正确计算31 + 31 + 28的总天数,不会出现漏算
内容的提问来源于stack exchange,提问作者FortuneCookie
相关产品推荐
相关产品推荐

