公司开发的门店系统中有这样一个功能,就是在预约模块可以查看某个客户当前月和下个月的预约数据。而这两个月的预约数据是通过传入不同的参数(年,月),请求两次接口拿到的。


3 月份的数据,传入 { year:2025, month: 3 }

4 月份的数据,传入 { year:2025, month: 4 }


项目功能截图.png


前天(2025-3-31)门店同事向我们反馈了一个 BUG,说客户 4 月份的预约数据看不到了。他们发给我的截图,3 月后面展示的是 5 月份的数据,直接跳过了 4 月。这就说明计算当前月的下一个月的逻辑出错了,3 后面是 4,现在却成了 5。其实这个功能上线有一段时间了,近期也没有人改动它,之前运行的好好的,怎么突然就出现 BUG 了呢?


看了下项目中的逻辑代码,挺简单的,就两行

const today = new Date()
today.setMonth(today.getMonth() + 1) // 计算下一个月


乍一看,没毛病呀,计算当前时间的下一个月。可问题就出在这,在浏览器控制台测试的结果如下:

控制台测试结果.png


那么具体原因是什么呢?

原因就是 setMonth() 方法与具体的日期是有关系的,特别是当涉及到月末日期时会出现特殊行为。

对于 2025-3-31 这个日期:

3 月有 31 天

4 月只有 30 天

当我们尝试将 2025-3-31 增加 1 个月时,日期就变成了 2025-4-31,而 4 月是没有 31 号的,所以这是一个无效的日期。而 JavaScript 的 Date 对象会自动处理这种 "溢出" 情况,当设置月份后导致日期无效(如 4 月 31 日),Date 对象会自动将日期调整为下个月的第 1 天。


所以正如上面控制台的测试结果一样, 2025-3-31 setMonth 加 1 之后,日期变成了 2025-5-1 。因此想要解决这个问题,我们计算月份的时候,忽略掉具体日期就行了。

const today = new Date()
const Y = today.getFullYear()
const M = today.getMonth()

const target = new Date(Y, M) // 只传入年月,忽略掉具体日期,日期不传:默认则是 1 号
target.setMonth(target.getMonth() + 1)
本文最后更新于 2025-04-03 11:06:32JAVASCRIPT
天生我材必有用,千金散尽还复来~~
作者:鄢云峰 YYF声明:转载请注明文章出处地址:https://yanyunfeng.com/article/77
评论
提交
Comments | 1 条评论
路人2025-04-23 17:56:20
#1 回复
66