js实现倒数日/纪念日功能:输入一个日期和重复类型,计算当天到该日期的天数

一、实现的功能

  1. 每月重复:接收一个[day]数组,其中day为日期,计算距离最近的这个日期的时间,遇到没有的月份会再往下一个月进行查询(适用于发薪日,月纪念日等)

  1. 每周重复:接受一个[week1,week2]数组,其中week为选中的星期值(可多选),计算距离最近的一个值的天数,其中星期日为0(适用于每周的休息日等,每周提醒等)

  1. 每年重复:接受一个[month,day]数组,其中month为月份,day为日期,计算距离最近的这个时间的天数(适用于生日,年纪念日等)

  1. 不重复:接受一个[year,month,day]数组,其中year为年份,month为月份,day为日期,计算距离这个日期已经过去了或还有多少天(适用于记录某件不重复的事)

其中以上数组内的参数数据类型都为Number,如果接受的是字符串请自行转换或修改getRepeatDay方法,最后返回出来的结果是一个天数的值;
当类型为不重复时,如果这个日期已经过去了,返回的是一个负数,需要根据是否负数判断是否已经过去;
当这个日期是今天时,返回0。

二、效果展示

表单选项

  1. 每月重复只能选择日期

  1. 每年重复 只能选择月日

  1. 每周重复 只能选择星期

  1. 不重复 选择一个年月日

  1. 效果展示(当天日期为2023年1月18日),想实际操作可以搜索微信小程序:快乐打工日记,进行查看

三、具体实现

  1. 获取当前时间的函数:返回一个对象

// 获取当前时间对象
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
    }
}
  1. 计算两个日期之间的天数:返回天数

/**
 * 计算两个日期之间的天数
 *  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;
}
  1. 计算距离该日期的天数:返回天数

/**
 *  计算距离该日期的天数
 *  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函数就可以获取到对应的天数啦

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值