首页 > 其他分享 >前端js实现计算请假时长

前端js实现计算请假时长

时间:2024-12-26 15:59:18浏览次数:5  
标签:请假 end start getHours 前端 js 2025 const setHours

接到一个需求,要完成计算请假时长(需要去掉法定节假日和周末,然后还要去掉午休时间,还要按照各种请假类型来判断,有些不需要去掉节假日和周末,懂的都懂),以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;
}

 

标签:请假,end,start,getHours,前端,js,2025,const,setHours
From: https://blog.csdn.net/m0_69765744/article/details/144746238

相关文章

  • quietflow.js-jquery背景层动画插件
    quietflow.js是一款可以制作炫酷页面背景层动画效果的jquery插件。该jquery插件内置了9种不同效果的背景层动画,你可以为页面轻松的添加背景动画效果。可用的背景层动画效果有:squareFlashvortexbouncingBallsshootingLinessimpleGradientstarfieldlayeredTrianglescorner......
  • Next.js 14 部署运维:从开发到生产的最佳实践
    在完成Next.js14应用的开发后,如何将其高效地部署到生产环境并进行可靠的运维管理是一个关键问题。本文将详细介绍Next.js14的部署策略和运维最佳实践。部署准备工作1.环境配置管理//next.config.js/**@type{import('next').NextConfig}*/constnextConfig=......
  • Next.js 14 性能优化:从首屏加载到运行时优化的最佳实践
    在现代Web应用中,性能优化直接影响用户体验和业务转化。Next.js14提供了多种内置的性能优化特性,今天我们就来深入探讨如何充分利用这些特性,以及一些实用的优化技巧。图片和字体优化1.图片优化Next.js的Image组件供了强大的图片优化功能://components/OptimizedIm......
  • AI 驱动的前端开发:从接入到应用的实战指南
    "能不能给我们的应用加上AI功能?"产品经理兴奋地问我。作为一个海外电商网站的前端负责人,我深知AI不是简单地调用几个API就完事了。特别是在前端应用中,如何优雅地集成AI能力,如何处理流式响应,如何优化用户体验,都是需要仔细考虑的问题。最近两个月,我们成功地在项目中......
  • Next.js 14 基础入门:从项目搭建到核心概念
    Next.js14带来了许多激动人心的新特性,包括局部渲染、ServerActions增强等。作为一名前端开发者,我最近在项目中升级到了Next.js14,今天就来分享一下从项目搭建到实际应用的完整过程。项目初始化首先,让我们创建一个全新的Next.js14项目:#使用create-next-app创建......
  • 学习threejs,THREE.RingGeometry 二维平面圆环几何体
    ......
  • EasyPlayer.js视频流媒体播放器windows播放器多窗口播放音量的控制方法
    随着互联网技术的飞速发展和移动设备的普及,流媒体服务已经成为人们消费娱乐内容的主要途径之一。流媒体行业已经成为一个巨大的娱乐产业生态,各个环节都在不断发生着创新和变革。这些技术的发展不仅改变了内容的创作和分发方式,也为用户带来了更加丰富和个性化的体验。那么在实际......
  • Vue - vue 前端项目基础框架搭建流程
    1.初始化项目pnpmcreatevue//添加路由支持pnpmaddvue-router//添加数据状态管理支持pnpmaddpinia//添加UI模块支持pnpmaddelement-plus//添加图标支持pnpmadd@element-plus/icons-vue//增加网络请求模块支持pnpmaddaxios//添加国际化支持pnpmadd......
  • H5流媒体播放器EasyPlayer.js遇到播放海康RTSP流时客户端连接兼容问题
    在选择好用的播放器时,要确保播放器支持H.265的硬件解码。例如,EasyPlayer.jsH5播放器支持MSEH264和H265硬解码,以及WebCodec、H264和H265硬解码,这有助于提升视频播放的性能和降低CPU使用率。遇到播放海康RTSP流时客户端连接兼容问题时,应该如何处理?问题说明程序兼容性的问题,如......
  • 前端面试题(详解跨域及其解决方案)
    跨域及其解决方案1.什么叫跨域?1含义:简单来说就是不同源之间进行访问2.什么是源(origin)1.源的组成部分2.示例(同源请求与非同源请求)3.总结『所处源』与『目标源』不一致,就是『非同源』,又称『异源』或『跨域』2.跨域会带来什么问题?例如有两个源:『源A』和『源B』......