自然月的计算
开发中经常碰到需要计算自然月的问题,比如筛选条件取最近一个月、最近三个月等。计算自然月的日期,不能通过简单的通过30天*倍数来计算,否则会有很大的误差,而是需要考虑跨月份的问题。如5月31号的上一个月,其实是4月30号,而不是4月31号,因为4月没有31号;4月30号的上个月是3月30号,而不是3月31号。
下面介绍两行代码即可搞定的自然年月计算的方法。
两行代码搞定自然月的计算
知识点:
- 先要获取目标月份的天数,怎么获取的简单技巧,这个是关键:
new Date(year, month+step+1, 0), 其中,
在加了步进月数step后,再+1, 即month+step+1,然后日期设置为0,
这行代码的意思是:再取目标月份的下一个月份1号的前1天(1-1=0)
这样就得到了目标月份的最后一天的日期,也即了目标月份的天数。 - 目标日期与目标月份的天数对比,取最小的,即是目标日期,比如3月31号的下一个月是4月30号,而不是4月31号
natureMonth(curDate, step){
let targetDateLastDay = new Date(curDate.getFullYear(), curDate.getMonth() + step + 1, 0);
return new Date(curDate.getFullYear(), curDate.getMonth() + step, Math.min(curDate.getDate(), targetDateLastDay.getDate()));
}
当然,为了方便,curDate可以添加支持string类型,并且返回yyyy-MM-dd类型的日期字符串
故最终代码为
natureMonth(curDate, step) {
if (!curDate || !step) return curDate;
if (typeof curDate === 'string') curDate = new Date(curDate.replace(/[\/|\.]/g, '-')) // new Date(str) 对str格式的,ios只支持yyyy-MM-dd
let targetDateLastDay = new Date(curDate.getFullYear(), curDate.getMonth() + step + 1, 0);
let targetDate = new Date(curDate.getFullYear(), curDate.getMonth() + step, Math.min(curDate.getDate(), targetDateLastDay.getDate()));
return formatDate(targetDate, 'yyyy-MM-dd')
}
formatDate(dateObj, format) {
let month = dateObj.getMonth() + 1,
date = dateObj.getDate();
return format.replace(/yyyy|MM|dd/g, field => {
switch (field) {
case 'yyyy':
return dateObj.getFullYear();
case 'MM':
return month < 10 ? '0' + month : month;
case 'dd':
return date < 10 ? '0' + date : date
}
})
}