一、实现的功能
每月重复:接收一个[day]数组,其中day为日期,计算距离最近的这个日期的时间,遇到没有的月份会再往下一个月进行查询(适用于发薪日,月纪念日等)
每周重复:接受一个[week1,week2]数组,其中week为选中的星期值(可多选),计算距离最近的一个值的天数,其中星期日为0(适用于每周的休息日等,每周提醒等)
每年重复:接受一个[month,day]数组,其中month为月份,day为日期,计算距离最近的这个时间的天数(适用于生日,年纪念日等)
不重复:接受一个[year,month,day]数组,其中year为年份,month为月份,day为日期,计算距离这个日期已经过去了或还有多少天(适用于记录某件不重复的事)
其中以上数组内的参数数据类型都为Number,如果接受的是字符串请自行转换或修改getRepeatDay方法,最后返回出来的结果是一个天数的值;
当类型为不重复时,如果这个日期已经过去了,返回的是一个负数,需要根据是否负数判断是否已经过去;
当这个日期是今天时,返回0。
二、效果展示
表单选项
每月重复只能选择日期
![](https://i-blog.csdnimg.cn/blog_migrate/970a61be427af669f85f490703d60278.png)
每年重复 只能选择月日
![](https://i-blog.csdnimg.cn/blog_migrate/0b4ab0dab56dfd2df2940a674337658e.png)
每周重复 只能选择星期
![](https://i-blog.csdnimg.cn/blog_migrate/42adf9558983838032c72d5932a57bd7.png)
不重复 选择一个年月日
![](https://i-blog.csdnimg.cn/blog_migrate/72ec2bdad2ca7d946610ead390facf52.png)
效果展示(当天日期为2023年1月18日),想实际操作可以搜索微信小程序:快乐打工日记,进行查看
![](https://i-blog.csdnimg.cn/blog_migrate/310d012f8f2af1039a5970789c66866e.png)
三、具体实现
获取当前时间的函数:返回一个对象
// 获取当前时间对象
const getNowDate = () => {
const date = new Date();
const year = date.getFullYear() // 年
const month = date.getMonth() + 1; // 月
const day = date.getDate(); // 日
const week = weekArr[date.getDay()];
return {
year,
month,
day,
hour,
minutes,
seconds,
week
}
}
计算两个日期之间的天数:返回天数
/**
* 计算两个日期之间的天数
* date1 开始日期 yyyy-MM-dd
* date2 结束日期 yyyy-MM-dd
* 开始日期大于结束日期,返回负数
*/
function getDaysBetween(date1, date2) {
var startDate = Date.parse(date1);
var endDate = Date.parse(date2);
var days = (endDate - startDate) / (1 * 24 * 60 * 60 * 1000);
return days;
}
计算距离该日期的天数:返回天数
/**
* 计算距离该日期的天数
* date 格式月重复[day] 年重复[month,day] 周重复[weekArr] 不重复[year,month,day]
* type 计算类型:1 月重复 2 年重复 3 周重复 4 不重复
* 如果为当天 返回0
*/
function getRepeatDay(date, type = 1) {
const {
year,
month,
week,
day
} = getNowDate();
let nowDate = getDateString(year, month, day);
let newDate = '';
let isFuture = false; // 是否未来的日期
// 当月的最后一天
const lastDay = new Date(year, month, 0).getDate()
// 获取年月日字符串
function getDateString(yearNum, monthNum, dayNum) {
return `${yearNum}-${monthNum<10?`0${monthNum}`:monthNum}-${dayNum<10?`0${dayNum}`:dayNum}`
}
// 计算相差的天
function compareDay(nowDay, newDay, future) {
if (future) {
// 异常判断(当月没有该日期)
if (newDay > lastDay) {
newDate = getDateString(year, month + 1, date[0])
return getDaysBetween(nowDate, newDate)
} else {
return newDay - nowDay
}
} else {
// 异常判断(下月没有该日期)
const nextLastDay = new Date(year, month + 1, 0).getDate()
// 传入为某个日期,格式转换
newDate = getDateString(year, month + 1, newDay)
if (newDay > nextLastDay) {
newDate = getDateString(year, month + 2, newDay)
}
return getDaysBetween(nowDate, newDate)
}
}
// 每月的该日重复
// date格式为[day] 如[1]代表每月1日进行提醒 其中99代表每个月的最后一天
if (type === 1) {
let newDay = date[0] === 99 ? lastDay : date[0];
isFuture = day < newDay;
// 如果为当天 返回0
if (day === newDay) {
return 0
} else {
return compareDay(day, newDay, isFuture)
}
}
// 每年的该月该日重复
// date格式为[month,day] 如[11,1]代表每年11月1日进行提醒
if (type === 2) {
const sameMonth = month === date[0];
const sameDay = day === date[1];
isFuture = (month < date[0]) || (sameMonth && day < date[1]);
// 如果为当天 返回0
if (sameMonth && sameDay) {
return 0
} else if (sameMonth) {
// 同月 计算日
return compareDay(day, date[1], isFuture)
} else {
// 不同月不同日
newDate = getDateString(isFuture ? year : year + 1, date[0], date[1])
return getDaysBetween(nowDate, newDate)
}
}
// 每周几重复
// date格式为星期数组 [0,1,2,3,4,5,6] 如[1,4]代表每周一和每周四进行提醒
if (type === 3) {
const nowWeek = new Date().getDay();
if (date.includes(nowWeek)) {
return 0
} else {
let arr = []; // 距离值
date.forEach((i) => {
if (i > nowWeek) {
arr.push(i - nowWeek);
} else {
arr.push(weekArr.length - nowWeek + i);
}
})
// 取最小值
return Math.min(...arr)
}
}
// 不重复
// date格式为[year,month,day] 如[2022,1,4]代表今天距离该天的日期
if (type === 4) {
newDate = getDateString(date[0], date[1], date[2])
// 只有在这种情况下返回值可能是负数
return getDaysBetween(nowDate, newDate)
}
}
四、使用方法
按照要求的参数格式调用getRepeatDay函数就可以获取到对应的天数啦