JS获取当月最后一天常见Bug与修正方案
本文分析JavaScript中通过下月首日减一天获取当月最后一天的常见逻辑缺陷。当日期为31号时,setMonth操作会导致日期溢出并自动进位,造成结果错误。通过先将日期重置为28号可避免此问题,确保获取准确的月末日期。
JavaScript日期处理技巧与常见陷阱
在深入讨论具体实现前,先分享一个JavaScript处理日期的实用技巧:若需获取上个月最后一天,只需将Date对象的日期参数设置为0即可实现。
var endDate = new Date();
//上个月最后一天
endDate.setDate(0);
接下来进入正题。
获取当月最后一天的常规逻辑
通常思路中,获取当前月最后一天的方法是:先获取下个月的第一天,再减去一天。基于此逻辑,常见的代码实现如下。
var date= new Date();
date.setMonth(date.getMonth() + 1);
//日期设置为0号, 0表示1号的前一天
let lastDay = date.setDate(0);
console.log('最后一天:' + new Date(lastDay).toLocaleString())
本文撰写日期为2019.08.21,因此控制台打印结果如下。
最后一天:2019/8/31 下午4:10:43
算法缺陷分析与原因解释
该算法是否存在潜在Bug尚不确定,为还原现场,我们从2019.01.31开始逐一测试。
var date= new Date(2019, 0, 31); //0 表示1月
date.setMonth(date.getMonth() + 1);
// 日期设置为0号, 0表示1号的前一天
let lastDay = date.setDate(0);
console.log('最后一天:' + new Date(lastDay).toLocaleString())
打印结果:
最后一天:2019/2/28 上午12:00:00
观察发现,我们将1月31号向后推一个月再向前减一天,理论上应得到1月31号,但实际输出为2月28号,证明上述代码存在逻辑缺陷。
这是为何?
我们可以列出月份天数分布:
1月 1 ....... 28 29 30 31 2月 1 ....... 28 3月 1 ....... 28 29 30 31
在JavaScript中,month + 1会被解析为:
当前日期数值 + 当月总天数
因此,示例中的date.setMonth(date.getMonth() + 1)等价于1月31号 + 31天。根据上述月份列表,计算结果即为3月3号。

切勿误以为month + 1仅表示月份加1,其实际含义是当前日期数值加上当月天数。
修正方案与完整代码实现
如何确保不会多跳一个月?
只要保证month + 1执行前日期不超过28号即可。具体如何实现?
推算过程如下:
- 31号 + 31 会超
- 30号 + 31 会超
- 29号 + 31 会超
- 28号 + 31 还是 28 号 刚好
关键在于将31回拨至28,因此只需额外添加以下代码:
date.setDate(28)
完整代码:
var date= new Date(2019, 0, 31); //0 表示1月
date.setDate(28)
date.setMonth(date.getMonth() + 1);
// 日期设置为0号, 0表示1号的前一天
let lastDay = date.setDate(0);
console.log('最后一天:' + new Date(lastDay).toLocaleString())
运行结果:
最后一天:2019/1/31 上午12:00:00
代码部署后可能存在的BUG无法实时知晓,事后为解决这些BUG,花费了大量时间进行log调试。此处顺便推荐一款好用的BUG监控工具Fundebug。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
JS语法错误会阻止加载吗?区分SyntaxError与资源加载失败
2026-11-05 16:08:46
JavaScript常见SyntaxError语法错误排查与修复方法
2026-11-05 13:58:44
JS中slice、substring和substr截取字符串的区别
2026-11-05 13:43:47
JS 转 TS 手动迁移最佳实践:从配置 tsconfig 到消除 any 类型
2026-11-05 11:53:32
为什么JS数组push后得到的是数字而不是数组?
2026-11-05 09:59:18
