最近公司做的一个请假模块,需要计算出请假时间,在网上查找了很多资料,都没有详细完整的实现方式,我就尝试自己写了一下
代码中用到了moment.js,不要忘了引入哦,不啰嗦,直接上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<script>
/**
* 计算请假时长
*
* @param {Object} options - 计算请假时长的配置选项
* @param {string} options.startTime - 请假开始时间(必填,格式为 'YYYY-MM-DD HH:mm')
* @param {string} options.endTime - 请假结束时间(必填,格式为 'YYYY-MM-DD HH:mm')
* @param {string} [options.workStartTime='08:30'] - 上班时间(可选,默认为 '08:30',格式为 'HH:mm')
* @param {string} [options.workEndTime='17:30'] - 下班时间(可选,默认为 '17:30',格式为 'HH:mm')
* @param {string} [options.restStartTime='12:00'] - 午休开始时间(可选,默认为 '12:00',格式为 'HH:mm')
* @param {string} [options.restEndTime='12:00'] - 午休结束时间(可选,默认为 '12:00',格式为 'HH:mm',默认无午休时间)
* @param {number[]} [options.workdays=[1,2,3,4,5]] - 工作日数组(可选,默认为 [1,2,3,4,5])
* @param {string[]} [options.excludeHolidays=[]] - 去除的节假日数组(可选,默认为空数组,格式为 'YYYY-MM-DD')
* @returns {number} 请假时长(小时)
*/
function calculateLeaveDuration(options) {
const {
startTime,
endTime,
workStartTime = '08:30',
workEndTime = '17:30',
restStartTime = '12:00',
restEndTime = '12:00',
workdays = [1, 2, 3, 4, 5],
excludeHolidays = [],
} = options;
// 无开始时间/结束时间/开始时间大于结束时间 返回0小时
if (!startTime || !endTime || startTime >= endTime) return 0
// 把请假时段处理成数组 每一项表示每一天的请假时间
let leaveDays = [] // { startTime: HH:mm, endTime: HH:mm, week: Number('周几'), date: YYYY-MM-DD}
// 判断请假开始结束时间是不是同一天 去除掉上班下班以外的时间 超出上下班时间将会格式化为上下班时间
if (moment(startTime).isSame(endTime, 'day')) {
leaveDays.push({
startTime: startTime.substring(11) < workStartTime ? workStartTime : startTime.substring(11),
endTime: endTime.substring(11) > workEndTime ? workEndTime : endTime.substring(11),
week: moment(startTime).day(), date: startTime.substring(0, 10)
})
} else {
let dateCache = moment(startTime).add(1, 'days').format("YYYY-MM-DD")
leaveDays.push({
startTime: startTime.substring(11) < workStartTime ? workStartTime : startTime.substring(11), endTime: workEndTime,
week: moment(startTime).day(), date: startTime.substring(0, 10)
})
while (dateCache < moment(endTime).format("YYYY-MM-DD")) {
leaveDays.push({
startTime: workStartTime, endTime: workEndTime,
week: moment(dateCache).day(), date: dateCache
})
dateCache = moment(dateCache).add(1, 'days').format("YYYY-MM-DD")
}
leaveDays.push({
startTime: workStartTime, endTime: endTime.substring(11) > workEndTime ? workEndTime : endTime.substring(11),
week: moment(endTime).day(), date: endTime.substring(0, 10)
})
}
// console.log(leaveDays); // 去除上下班以外的时间
let removeWeekendHolidays = leaveDays.filter(item => workdays.includes(item.week) && !excludeHolidays.includes(item.date))
// console.log(removeWeekendHolidays); // 去除工作日/节假日以外的时间
// 去除午休时间
const rest_start = moment(restStartTime, 'HH:mm');
const rest_end = moment(restEndTime, 'HH:mm');
const restDuration = moment.duration(rest_end.diff(rest_start)).asMinutes();
removeWeekendHolidays.forEach(item => {
const start_time = moment(item.startTime, 'HH:mm');
const end_time = moment(item.endTime, 'HH:mm');
let leaveDuration = moment.duration(end_time.diff(start_time)).asMinutes();
if (start_time.isBefore(rest_end) && end_time.isAfter(rest_start)) {
const intersectionStart = moment.max(start_time, rest_start);
const intersectionEnd = moment.min(end_time, rest_end);
const intersectionDuration = moment.duration(intersectionEnd.diff(intersectionStart)).asMinutes();
leaveDuration -= intersectionDuration;
}
item.leaveHour = Math.max(leaveDuration / 60, 0); // 每一天的请假时长
})
// 返回请假时长
return + removeWeekendHolidays.reduce((sum, item) => sum + Number(item.leaveHour || 0), 0).toFixed(2)
}
// example
const options = {
startTime: '', endTime: '',
workStartTime: '08:30', workEndTime: '17:30',
restStartTime: '12:00', restEndTime: '13:00',
workdays: [1, 2, 3, 4, 5],
excludeHolidays: ['2023-10-01', '2023-10-02', '2023-10-03', '2023-10-04', '2023-10-05']
}
options.startTime = `2023-07-07 08:30`
options.endTime = `2023-07-07 17:30`
console.log(`请假时长为${calculateLeaveDuration(options)}小时`);
</script>
</html>
Tips:注释不能完整的描述清楚代码的思路,仅供参考,有啥问题请反馈