前端js实现计算请假时长

接到一个需求,要完成计算请假时长(需要去掉法定节假日和周末,然后还要去掉午休时间,还要按照各种请假类型来判断,有些不需要去掉节假日和周末,懂的都懂),以2025年的法定节假日为例,上代码

不包含法定节假日和周末,哦对了还要加上调休(可恶的调休)

// 定义2025年的法定节假日和调休日
const holidays2025 = [
  '2025-01-01', // 元旦
  '2025-01-28',
  '2025-01-29',
  '2025-01-30',
  '2025-01-31', // 春节
  '2025-02-01',
  '2025-02-02',
  '2025-02-03',
  '2025-02-04',
  '2025-04-04',
  '2025-04-05',
  '2025-04-06', // 清明节
  '2025-05-01',
  '2025-05-02',
  '2025-05-03',
  '2025-05-04',
  '2025-05-05', // 劳动节
  '2025-05-31',
  '2025-06-01',
  '2025-06-02', // 端午节
  '2025-10-01',
  '2025-10-02',
  '2025-10-03',
  '2025-10-04', // 国庆节和中秋节
  '2025-10-05',
  '2025-10-06',
  '2025-10-07',
  '2025-10-08',
];

// 因调休需要上班的周末
const workdays2025 = [
  '2025-01-26', // 星期日
  '2025-02-08', // 星期六
  '2025-04-27', // 星期日
  '2025-09-28', // 星期日
  '2025-10-11', // 星期六
];

// 工具函数:判断某天是否是工作日
function isWorkday(date) {
  const day = date.getDay(); // 0 表示星期日, 6 表示星期六
  const dateStr = date.toISOString().split('T')[0]; // 转为 YYYY-MM-DD 格式
  if (holidays2025.includes(dateStr)) {
    return false; // 法定节假日
  }
  if (workdays2025.includes(dateStr)) {
    return true; // 调休工作日
  }
  return day !== 0 && day !== 6; // 排除周六和周日
}

// 工具函数:计算两个日期之间的工作时长(小时),不包含午休
export function calculateLeaveHours(startTime, endTime) {
  const workStartHour = 9; // 工作日开始时间
  const workEndHour = 18; // 工作日结束时间
  const lunchStartHour = 12; // 午休开始时间
  const lunchEndHour = 13; // 午休结束时间

  let totalHours = 0;

  // 转为 Date 对象
  const start = new Date(startTime);
  const end = new Date(endTime);

  // 如果开始时间或结束时间超出工作时间范围,则调整到工作时间内
  if (start.getHours() < workStartHour) {
    start.setHours(workStartHour, 0, 0, 0); // 设置到早上 9 点
  } else if (start.getHours() >= lunchStartHour && start.getHours() < lunchEndHour) {
    start.setHours(lunchEndHour, 0, 0, 0);
  } else if (start.getHours() >= workEndHour) {
    start.setHours(workEndHour, 0, 0, 0); // 设置到晚上 6 点
  }

  if (end.getHours() < workStartHour) {
    end.setHours(workStartHour, 0, 0, 0); // 设置到早上 9 点
  } else if (end.getHours() >= lunchStartHour && end.getHours() < lunchEndHour) {
    end.setHours(lunchStartHour, 0, 0, 0);
  } else if (end.getHours() >= workEndHour) {
    end.setHours(workEndHour, 0, 0, 0); // 设置到晚上 6 点
  }

  // 遍历日期区间
  let current = new Date(start);
  while (current < end) {
    if (isWorkday(current)) {
      // 计算当天的工作时间,排除午休时间
      const dayEnd = new Date(current);
      dayEnd.setHours(workEndHour, 0, 0, 0);
      if (dayEnd > end) {
        dayEnd.setTime(end.getTime()); // 如果超出结束时间,则只计算到结束时间
      }

      const dayStart = new Date(current);
      if (dayStart < start) {
        dayStart.setTime(start.getTime()); // 如果开始时间在当天之后,调整为当天开始时间
      }

      // 中午12点到1点的午休时间不算
      const dayStartTime = Math.max(dayStart.getTime(), current.getTime());
      const dayEndTime = Math.min(dayEnd.getTime(), end.getTime());

      const workTimeInDay = (dayEndTime - dayStartTime) / (1000 * 60 * 60); // 转为小时
      let lunchBreak = 0;
      if (dayStart.getHours() < lunchEndHour && dayEnd.getHours() > lunchStartHour) {
        lunchBreak = 1; // 只有在时间范围内有午休,才扣除1小时
      }

      totalHours += workTimeInDay - lunchBreak;
    }

    // 移动到下一天
    current.setDate(current.getDate() + 1);
    current.setHours(workStartHour, 0, 0, 0); // 设置为下一天的早上 9 点
  }

  return totalHours;
}

包含节假日和周末

// 包含周六周天,国家节假日

// 工具函数:计算两个日期之间的工作时长(小时),不包含午休
export function calculateLeaveTotalHours(startTime, endTime) {
  const workStartHour = 9; // 工作日开始时间(9:00)
  const workEndHour = 18; // 工作日结束时间(18:00)
  const lunchStartHour = 12; // 午休开始时间(12:00)
  const lunchEndHour = 13; // 午休结束时间(13:00)

  let totalHours = 0;

  // 转为 Date 对象
  const start = new Date(startTime);
  const end = new Date(endTime);

  // 如果开始时间超出工作时间范围,则调整到工作时间内
  if (start.getHours() < workStartHour) {
    start.setHours(workStartHour, 0, 0, 0); // 设置到早上 9 点
  } else if (start.getHours() >= lunchStartHour && start.getHours() < lunchEndHour) {
    start.setHours(lunchEndHour, 0, 0, 0);
  } else if (start.getHours() >= workEndHour) {
    start.setHours(workEndHour, 0, 0, 0); // 设置到晚上 6 点
  }

  // 如果结束时间超出工作时间范围,则调整到工作时间内
  if (end.getHours() < workStartHour) {
    end.setHours(workStartHour, 0, 0, 0); // 设置到早上 9 点
  } else if (end.getHours() >= lunchStartHour && end.getHours() < lunchEndHour) {
    end.setHours(lunchStartHour, 0, 0, 0);
  } else if (end.getHours() >= workEndHour) {
    end.setHours(workEndHour, 0, 0, 0); // 设置到晚上 6 点
  }

  // 遍历日期区间
  let current = new Date(start);
  while (current < end) {
    // 计算当天的有效工作时间
    const dayEnd = new Date(current);
    dayEnd.setHours(workEndHour, 0, 0, 0); // 设置为当天的晚上6点

    // 如果结束时间早于当天结束时间,则调整为结束时间
    if (dayEnd > end) {
      dayEnd.setTime(end.getTime());
    }

    const dayStart = new Date(current);
    dayStart.setHours(workStartHour, 0, 0, 0); // 设置为当天的9点

    // 如果开始时间晚于当天开始时间,则调整为开始时间
    if (dayStart < start) {
      dayStart.setTime(start.getTime());
    }

    // 计算当天有效工作时长,排除午休时间(12:00-13:00)
    let workTimeInDay = (dayEnd - dayStart) / (1000 * 60 * 60); // 转为小时

    // 中午12点到1点的午休时间不算
    const lunchBreakStart = new Date(dayStart);
    lunchBreakStart.setHours(lunchStartHour, 0, 0, 0);
    const lunchBreakEnd = new Date(dayStart);
    lunchBreakEnd.setHours(lunchEndHour, 0, 0, 0);

    // 如果当天的有效工作时间包括午休时间,则扣除1小时
    if (dayStart < lunchBreakEnd && dayEnd > lunchBreakStart) {
      workTimeInDay -= 1; // 扣除午休时间1小时
    }

    // 累加当天的有效工作时间
    totalHours += workTimeInDay;

    // 移动到下一天
    current.setDate(current.getDate() + 1);
    current.setHours(workStartHour, 0, 0, 0); // 设置为下一天的早上 9 点
  }

  return totalHours;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值