JS---计算请假时长,按大小周计算

JS计算请假时长:

<script type="text/javascript">
/**
 * 计算两个时间点之间的有效工作时间(单位:小时,保留2位小数)
 * @param {string|Date} startTime - 请假开始时间
 * @param {string|Date} endTime - 请假结束时间
 * @param {Array<{start: string, end: string}>} workShifts - 工作时间段数组(如 ["08:45-12:00", "13:30-18:00"])
 * @param {number} [firstWorkdayOfWeek=1] - 大小周起始周(1=第1周上班,0=第1周休息)
 * @returns {number} 有效工作时间(小时)
 */
function calculateLeaveHours(startTime, endTime, workShifts, firstWorkdayOfWeek = 1) {
    /**
     * 判断是否是大小周的休息周六
     * @param {Date} date - 要判断的日期
     * @param {number} firstWorkdayOfWeek - 大小周起始周(1=第1周上班,0=第1周休息)
     * @returns {boolean} - 是否是休息周六
     */
    const isRestSaturday = function(date, firstWorkdayOfWeek) {
      if (date.getDay() !== 6) return false; // 不是周六,直接返回 false

      const year = date.getFullYear();
      const month = date.getMonth();
      const day = date.getDate();

      // 获取当月第1天的日期
      const firstDayOfMonth = new Date(year, month, 1);
      // 获取当月第1天是周几(0=周日,1=周一,...,6=周六)
      const firstDayWeekday = firstDayOfMonth.getDay();

      // 计算当月第1个周六的日期
      const firstSaturday = 1 + (5 - firstDayWeekday + 7) % 7;

      // 计算当前日期是当月的第几个周六
      const daysSinceFirstSaturday = day - firstSaturday;
      const weekNumber = Math.floor(daysSinceFirstSaturday / 7) + 1;

      // 判断是否是休息周六(大小周逻辑)
      return (weekNumber + firstWorkdayOfWeek) % 2 === 0;
    }

    /**
     * 解析时间字符串("HH:mm")返回 Date 对象(当天时间)
     */
    const parseTime = function(timeStr) {
      const [hours, minutes] = timeStr.split(":").map(Number);
      const date = new Date();
      date.setHours(hours, minutes, 0, 0);
      return date;
    }

  const workPeriods = workShifts.map(shift => {
    const [start, end] = shift.split("-");
    return { start: parseTime(start), end: parseTime(end) };
  });

  const startDate = new Date(startTime);
  const endDate = new Date(endTime);

  if (endDate <= startDate) return 0;

  let totalHours = 0;
  const currentDate = new Date(startDate);

  while (currentDate <= endDate) {
    const year = currentDate.getFullYear();
    const month = currentDate.getMonth();
    const day = currentDate.getDate();

    // 判断是否是大小周的休息周六
    if (isRestSaturday(currentDate, firstWorkdayOfWeek)) {
      currentDate.setDate(currentDate.getDate() + 1);
      continue;
    }

    // 判断是否是周日(无论大小周,周日都休息)
    if (currentDate.getDay() === 0) {
      currentDate.setDate(currentDate.getDate() + 1);
      continue;
    }

    // 计算当天的工作时间
    const dayStart = new Date(year, month, day, 0, 0, 0);
    const dayEnd = new Date(year, month, day, 23, 59, 59);
    const actualStart = new Date(Math.max(startDate, dayStart));
    const actualEnd = new Date(Math.min(endDate, dayEnd));

    if (actualEnd <= actualStart) {
      currentDate.setDate(currentDate.getDate() + 1);
      continue;
    }

    // 计算当天所有工作时间段的有效时间
    let dailyHours = 0;
    for (const period of workPeriods) {
      const periodStart = new Date(dayStart);
      periodStart.setHours(
        period.start.getHours(),
        period.start.getMinutes(),
        period.start.getSeconds()
      );
      const periodEnd = new Date(dayStart);
      periodEnd.setHours(
        period.end.getHours(),
        period.end.getMinutes(),
        period.end.getSeconds()
      );

      const validStart = new Date(Math.max(actualStart, periodStart));
      const validEnd = new Date(Math.min(actualEnd, periodEnd));

      if (validEnd > validStart) {
        dailyHours += (validEnd - validStart) / (1000 * 60 * 60);
      }
    }

    totalHours += dailyHours;
    currentDate.setDate(currentDate.getDate() + 1);
  }

  return parseFloat(totalHours.toFixed(2));
}

// ===== 测试示例 =====
const workShifts = ["08:45-12:00", "13:30-18:00"];

// 测试大小周(第1周上班,第2周休息)
// console.log(calculateLeaveHours("2024-01-06 09:00", "2024-01-06 17:00", workShifts, 1)); // 0 小时(第2周周六,休息)
// console.log(calculateLeaveHours("2024-01-13 09:00", "2024-01-13 17:00", workShifts, 1)); // 7.25 小时(第3周周六,上班)
// console.log(calculateLeaveHours("2024-01-20 09:00", "2024-01-20 17:00", workShifts, 1)); // 0 小时(第4周周六,休息)

// 测试大小周(第1周休息,第2周上班)
// console.log(calculateLeaveHours("2024-01-06 09:00", "2024-01-06 17:00", workShifts, 0)); // 7.25 小时(第2周周六,上班)
// console.log(calculateLeaveHours("2024-01-13 09:00", "2024-01-13 17:00", workShifts, 0)); // 0 小时(第3周周六,休息)

console.log(calculateLeaveHours("2025-08-08 08:45", "2025-08-08 12:00", workShifts, 1)); // 0 
</script>
posted @ 2025-08-09 11:27  帅到要去报警  阅读(148)  评论(0)    收藏  举报