根据当年节假日和非工作时间计算请假时间-获取每个月的节假日,计算每个月的工作日时间进度,节假日每年更新(2026)
·
根据需求请假时间要排除法定节假日和非工作时间
1.获取当年的节假日
节假日是每年更新的,没有固定接口,需要手动录入
个人根据官方的节假日整理了当年的所有节假日,可以根据个人需求进行修改
// 获取每个月的节假日,如果当月没有节假日就默认星期六星期天
holidays: [
[1, 2, 3, 10, 11, 17, 18, 24, 25, 31],// 1月
[1, 7, 8, 15, 16, 17, 18, 19, 20, 21, 22, 23],// 2月
[],// 3月
[4, 5, 6, 11, 12, 18, 19, 25, 26],// 4月
[1, 2, 3, 4, 5, 10, 16, 17, 23, 24, 30, 31],// 5月
[6, 7, 13, 14, 19, 20, 21, 27, 28],// 6月
[],// 7月
[],// 8月
[5, 6, 12, 13, 19, 25, 26, 27],// 9月
[1, 2, 3, 4, 5, 6, 7, 11, 17, 18, 24, 25, 31],// 10月
[],// 11月
[],// 12月
]
2.使用当年的节假日进行判断
这里是封装的计算方法,传入开始时间和结束时间 时间格式为:年-月-日 时:分
里面定义了上班开始结束时间和中午休息时间,可以自定义
// 计算工作时间调休小时数
calculateLeaveTime(startTime, endTime) {
const workStartHour = 9; // 工作开始时间 09:00
const workEndHour = 18; // 工作结束时间 18:00
const restStartHour = 12; // 午休开始 12:00
const restEndHour = 13; // 午休结束 13:00
const start = new Date(startTime);
const end = new Date(endTime);
if (end <= start) {
this.tips = true;
return "0小时";
}
let totalHours = 0;
let current = new Date(start);
current.setHours(0, 0, 0, 0); // 从当天0点开始
const endDate = new Date(end);
endDate.setHours(0, 0, 0, 0);
// 处理每一天
while (current <= endDate) {
const currentDate = new Date(current);
// 首先检查是否是工作日
if (!this.isWorkDay(currentDate)) {
current.setDate(current.getDate() + 1);
continue;
}
// 如果是同一天
if (
this.isSameDay(currentDate, start) &&
this.isSameDay(currentDate, end)
) {
totalHours += this.calculateHoursForSameDay(
start,
end,
workStartHour,
workEndHour,
restStartHour,
restEndHour
);
}
// 第一天
else if (this.isSameDay(currentDate, start)) {
totalHours += this.calculateHoursForFirstDay(
start,
workStartHour,
workEndHour,
restStartHour,
restEndHour
);
}
// 最后一天
else if (this.isSameDay(currentDate, end)) {
totalHours += this.calculateHoursForLastDay(
end,
workStartHour,
workEndHour,
restStartHour,
restEndHour
);
}
// 中间完整工作日
else {
totalHours += this.calculateFullWorkDayHours(
workStartHour,
workEndHour,
restStartHour,
restEndHour
);
}
// 增加一天
current.setDate(current.getDate() + 1);
}
this.tips = false;
return parseFloat(totalHours.toFixed(1)) + "小时";
},
// 辅助方法
isSameDay(date1, date2) {
return (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
},
isWorkDay(date) {
const day = date.getDay();
const month = date.getMonth();
const dateNum = date.getDate();
// 检查周末
if (day === 0 || day === 6) {
return false;
}
// 检查节假日
const holidayArr = this.$store.state.holidays[month];
if (holidayArr && holidayArr.includes(dateNum)) {
return false;
}
return true;
},
calculateHoursForSameDay(
start,
end,
workStart,
workEnd,
restStart,
restEnd
) {
const startHour = start.getHours() + start.getMinutes() / 60;
const endHour = end.getHours() + end.getMinutes() / 60;
// 调整到工作时间范围内
const adjustedStart = Math.max(startHour, workStart);
const adjustedEnd = Math.min(endHour, workEnd);
if (adjustedEnd <= adjustedStart) return 0;
// 计算总时长,扣除午休时间
let total = adjustedEnd - adjustedStart;
// 如果时间段跨越午休,扣除午休时间
if (adjustedStart < restEnd && adjustedEnd > restStart) {
const overlapStart = Math.max(adjustedStart, restStart);
const overlapEnd = Math.min(adjustedEnd, restEnd);
total -= Math.max(0, overlapEnd - overlapStart);
}
return Math.max(0, total);
},
calculateHoursForFirstDay(start, workStart, workEnd, restStart, restEnd) {
const startHour = start.getHours() + start.getMinutes() / 60;
const adjustedStart = Math.max(startHour, workStart);
const adjustedEnd = workEnd;
if (adjustedEnd <= adjustedStart) return 0;
let total = adjustedEnd - adjustedStart;
if (adjustedStart < restEnd && adjustedEnd > restStart) {
const overlapStart = Math.max(adjustedStart, restStart);
const overlapEnd = Math.min(adjustedEnd, restEnd);
total -= Math.max(0, overlapEnd - overlapStart);
}
return Math.max(0, total);
},
calculateHoursForLastDay(end, workStart, workEnd, restStart, restEnd) {
const endHour = end.getHours() + end.getMinutes() / 60;
const adjustedStart = workStart;
const adjustedEnd = Math.min(endHour, workEnd);
if (adjustedEnd <= adjustedStart) return 0;
let total = adjustedEnd - adjustedStart;
if (adjustedStart < restEnd && adjustedEnd > restStart) {
const overlapStart = Math.max(adjustedStart, restStart);
const overlapEnd = Math.min(adjustedEnd, restEnd);
total -= Math.max(0, overlapEnd - overlapStart);
}
return Math.max(0, total);
},
calculateFullWorkDayHours(workStart, workEnd, restStart, restEnd) {
// 完整工作日时长 = (工作结束-工作开始) - 午休时长
return workEnd - workStart - (restEnd - restStart);
},


这里按每天八小时计算,排除了2024年法定节假日 劳动节的调休 一共使用了工作时间的32小时
3.计算当月工作日时间进度
// 计算工作日时间进度
// 获取当前时间
const now = new Date();
// 获取当前年份和月份
const currentYear = now.getFullYear();
const currentMonth = now.getMonth();
// 获取vuex里面存储的节假日
let holidays = this.$store.state.holidays[currentMonth]
// console.log("当月节假日", holidays);
// 计算当月天数
const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
// 当月几号
const dayOfMonth = now.getDate();
// console.log("当月天数:", daysInMonth);
// console.log("当月的第", dayOfMonth, "天");
// 工作日天数
let workday = 0;
// 当前工作日天数
let Month = 0;
// 当前时间进度
let num = "0%";
// 判断是否设置节假日
if (holidays.length) {
// 自定义节假日
workday = daysInMonth - holidays.length;
// console.log("自定义工作日", workday);
// 默认已工作日
for (let i = 1; i < dayOfMonth + 1; i++) {
if (!holidays.includes(i)) {
Month++;
}
}
num = Month / workday;
} else {
// 循环默认天数
for (let i = 1; i < daysInMonth + 1; i++) {
let date = new Date(
new Date().getFullYear(),
new Date().getMonth(),
i
);
// 遍历每天获取星期几
let x = date.getDay();
// 不是节假日工作日就加一
if (![0, 6].includes(x)) {
workday++;
}
}
// console.log("默认工作日", workday);
// 默认已工作日
for (let i = 1; i < dayOfMonth + 1; i++) {
let date = new Date(
new Date().getFullYear(),
new Date().getMonth(),
i
);
// 遍历每天获取星期几
let x = date.getDay();
// 不是节假日工作日就加一
if (![0, 6].includes(x)) {
Month++;
}
}
num = Month / workday;
}
// console.log("已工作", Month, "天");
// console.log("时间进度" + (num * 100).toFixed(1) + "%");
// 赋值时间进度
this.less_day = (num * 100).toFixed(1).replace(/\.0$/, "") + "%";
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)