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