编辑代码

//计算加班时效

import chineseDays from 'chinese-days';
const {
    isWorkday
} = chineseDays;

const WORK_START_TIME = 9;
const WORK_END_TIME = 18;
const WORK_START_TIME1 = 8.5;
const WORK_END_TIME1 = 17.5;

let work_start_time, work_end_time;
/**
 *
 * @param {*Number} num
 * @returns 分离出来的整数和小数
 */
const separation = (num) => {
    let intNum = 0,
        floatNum = 0.0;
    floatNum = num % 1;
    intNum = num - floatNum;
    return {
        intNum,
        floatNum
    };
};
//规范hour:minutes的值
const standardTime = (hour, min) => {
    let shour = hour,
        smin = min;
    //规范开始工作时间和结束工作时间
    smin = (shour >= work_start_time && shour <= work_end_time) ? null : smin;
    shour = (shour >= work_start_time && shour <= work_end_time) ? null : shour;

    return {
        shour,
        smin
    };
};
//按小时加班,确保sTime和eTime在同一天,且当天不是节假日
const overtimeByhours = (sTime, eTime) => {
    let hours = 0,
        result = null;
    let shour = sTime.getHours(),
        smin = sTime.getMinutes();
    let ehour = eTime.getHours(),
        emin = eTime.getMinutes();
    let stTime = standardTime(shour, smin);
    let etTime = standardTime(ehour, emin);
    if (stTime.shour != null) {
        if (etTime.shour != null) {
            //在work_start_time 之前,work_end_time之后都有加班时间
            if (stTime.shour <= work_end_time) {
                let res1 = new Date(eTime.getFullYear(), eTime.getMonth(), eTime.getDate(), etTime.shour, etTime.smin) -
                    new Date(eTime.getFullYear(), eTime.getMonth(), eTime.getDate(), work_end_time, 0);
                let res2 = new Date(sTime.getFullYear(), sTime.getMonth(), sTime.getDate(), work_start_time, 0) -
                    new Date(sTime.getFullYear(), sTime.getMonth(), sTime.getDate(), stTime.shour, stTime.smin);
                result = res1 + res2;
            } else {
                result = new Date(eTime.getFullYear(), eTime.getMonth(), eTime.getDate(), etTime.shour, etTime.smin) -
                    new Date(sTime.getFullYear(), sTime.getMonth(), sTime.getDate(), stTime.shour, stTime.smin);
            }
        } else {
            //在work_start_time 之前加班时间
            result = new Date(eTime.getFullYear(), eTime.getMonth(), eTime.getDate(), work_start_time, 0) -
                new Date(sTime.getFullYear(), sTime.getMonth(), sTime.getDate(), stTime.shour, stTime.smin)
        }
    } else {
        if (etTime.shour != null) {
            //在work_end_time 之后加班时间
            result = new Date(eTime.getFullYear(), eTime.getMonth(), eTime.getDate(), etTime.shour, etTime.smin) -
                new Date(eTime.getFullYear(), eTime.getMonth(), eTime.getDate(), work_end_time, 0);
        } else {
            //在工作时间段内计算加班时间
            result = 0;
        }
    }
    hours = result / 1000 / 60 / 60;
    return hours;
};

const overtimeBydays = (sTime, eTime, complement = 0) => {
    let sday = sTime.getDate();
    let result = eTime - sTime;
    let days = result / 1000 / 60 / 60 / 24 + complement;
    let {
        intNum,
        floatNum
    } = separation(days);
    let weekdays = 0;
    for (let i = 0; i < Math.round(days); i++) {
        let nowDay = new Date(new Date(sTime).setDate(sday + i));
        if (checkDay(nowDay)) {
            weekdays++;
        }
    }
    days = intNum + (floatNum > 0.5 ? 1 : floatNum === 0 ? 0 : 0.5);
    days -= weekdays;
    return {
        days,
        weekdays
    };
};
//判断日期是否处于周六、周日
//是否为节假日可配合插件(https://www.jsdelivr.com/package/npm/chinese-days)使用
const checkDay = (time) => {
    let flag = isWorkday(time)
    return !flag;
};

/**
 * 计算节假日加班时间
 *  @param {*Date} sTime
 *  @param {*Date} eTime
 *  @returns Number:加班时长:小时
 */
const overtimeHolidays = (sTime, eTime) => {
    let result;
    result = (new Date(eTime) - new Date(sTime)) / 1000 / 60 / 60;
    return result;
}

/**
 *
 * @param {*Date} sTime
 * @param {*Date} eTime
 * @returns Number:加班时长:小时
 */
const calcHour = (sTime, eTime, type) => {
    work_start_time = type == '2' ? WORK_START_TIME1 : WORK_START_TIME;
    work_end_time = type == '2' ? WORK_END_TIME1 : WORK_END_TIME;
    let hours = 0,
        sday = sTime.getDate(),
        eday = eTime.getDate();

    if (sday === eday) {
        //1.同一天加班
        hours = checkDay(sTime) ? overtimeHolidays(sTime, eTime) : overtimeByhours(sTime, eTime);
    } else {
        /*2.不同天加班
         */
        let ds = new Date(sTime.getFullYear(), sTime.getMonth(), sTime.getDate() + 1, 0, 1),
            de = new Date(eTime.getFullYear(), eTime.getMonth(), eTime.getDate(), 0, 1);
        let d = overtimeBydays(ds, de); //除去第一天与最后一天的天数(包括工作日和节假日)
        let r1 = checkDay(sTime) ? overtimeHolidays(sTime, new Date(sTime).setHours(24)) : overtimeByhours1(sTime, 24); //计算第一天加班时长
        let r2 = checkDay(new Date(eTime).setHours(0)) ? overtimeHolidays(new Date(eTime).setHours(0), eTime) : overtimeByhours1(0, eTime); //计算最后一天加班时长
        console.log(d, r1, r2)
        hours = r1 + r2 + d.days * 15 + d.weekdays * 24;
    }
    return hours < 0 ? 0 : hours;
};

const overtimeByhours1 = (start, end) => {
    let hours, shour, smin, ehour, emin;
    shour = Math.floor(work_start_time);
    smin = work_start_time == 8.5 ? 30 : 0;
    ehour = Math.floor(work_end_time);
    emin = work_end_time == 17.5 ? 30 : 0;
    if (start) {
        if (start >= new Date(start).setHours(shour, smin) && start <= new Date(start).setHours(ehour, emin)) {
            hours = work_start_time == 8.5 ? 6.5 : 6;
        } else if (start < new Date(start).setHours(shour, smin)) {
            let res1 = (new Date(start).setHours(shour, smin) - start) / 1000 / 60 / 60;
            hours = work_start_time == 8.5 ? 6.5 + res1 : 6 + res1;
        } else if (start > new Date(start).setHours(ehour, emin)) {
            hours = (new Date(start).setHours(24) - start) / 1000 / 60 / 60;
        }
    } else {
        if (end >= new Date(end).setHours(shour, smin) && end <= new Date(end).setHours(ehour, emin)) {
            hours = work_start_time == 8.5 ? 8.5 : 9;
        } else if (end < new Date(end).setHours(shour, smin)) {
            hours = (end - new Date(end).setHours(0)) / 1000 / 60 / 60;
        } else if (end > new Date(end).setHours(ehour, emin)) {
            let res1 = (end - new Date(end).setHours(ehour, emin)) / 1000 / 60 / 60;
            hours = work_start_time == 8.5 ? 8.5 + res1 : 9 + res1;
        }
    }
    return hours
}




/**
 *
 * @param {*开始时间} sTime
 * @param {*结束时间} eTime
 * @returns 加班时长:天
 */
const calcDay = (sTime, eTime) => {
    let days = overtimeBydays(sTime, eTime, 1);
    return days;
};

export {
    calcHour,
    calcDay
};