编辑代码

//计算加班时效

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
};