JavaScript中给定日期下月计算异常:3月31日为何变为5月?
为什么给2018-03-31加一个月会得到5月?
这个问题我之前也碰到过,其实是JavaScript Date对象的一个“特性”导致的,咱们来拆解一下:
问题根源
当你调用d.setMonth(d.getMonth() + 1)时,JavaScript会尝试把日期设置为原日期的日数对应的下一个月的同一天。比如你输入的是3月31日,它会尝试设置成4月31日,但4月只有30天,这个日期不存在,所以Date对象会自动“进位”——把4月31日转换成5月1日(相当于4月的30天过完再加1天),这就是为什么你得到的是5月而不是4月。
你原来的代码是这样的:
var d = new Date('2018-03-31'); dt = new Date(d.setMonth(d.getMonth() + 1)); document.getElementById("demo").innerHTML = dt;
解决办法
这里提供两种可靠的方案来避免这种日期溢出的问题:
方案一:先取下月第一天,再调整到合适的日期
这种方法会先获取下个月的第一天,然后把日期设置为原日期的日数和下个月最后一天的日数中较小的那个,这样就能保证日期不会溢出:
var d = new Date('2018-03-31'); // 获取下个月的第一天 var nextMonthFirstDay = new Date(d.getFullYear(), d.getMonth() + 1, 1); // 获取下个月的最后一天(设置日期为0会自动返回上月最后一天,这里就是下个月的最后一天) var nextMonthLastDay = new Date(nextMonthFirstDay.getFullYear(), nextMonthFirstDay.getMonth() + 1, 0); // 取原日期和下月最后一天的较小值,作为目标日期的日数 var targetDate = new Date( nextMonthFirstDay.getFullYear(), nextMonthFirstDay.getMonth(), Math.min(d.getDate(), nextMonthLastDay.getDate()) ); document.getElementById("demo").innerHTML = targetDate;
方案二:检查月份是否溢出,回退到当月最后一天
这种方法先尝试加一个月,然后检查结果的月份是否符合预期,如果不符合(说明溢出了),就把日期设置为当月的最后一天:
var d = new Date('2018-03-31'); var dt = new Date(d); dt.setMonth(dt.getMonth() + 1); // 检查调整后的月份是否是原月份+1(取模12是为了处理12月加1到1月的情况) if (dt.getMonth() !== (d.getMonth() + 1) % 12) { dt.setDate(0); // setDate(0)会返回当前月份的最后一天 } document.getElementById("demo").innerHTML = dt;
这两种方法都能正确返回2018-04-30,而不是跳到5月。
内容的提问来源于stack exchange,提问作者mpsbhat
相关产品推荐
相关产品推荐

