最近有一个需求,选择两个日期后,计算请假总的小时数

要求:

  1. 日期之间如果有法定节假日,需要剔除计算
  2. 已设置的非考勤时间段,需要剔除计算
  3. 只统计请假日期范围内需要出勤的时间总和

举例:

请假10月1日至10月10日,其中10月1日至10月7日为法定节假日,10月8日、10月9日、10月10日为考勤日期,考勤时间段为9:00-12:00, 13:00-18:00,由此可得请假小时为24个小时

思考:

因为考勤时间可能存在多个时间段和多个筛选日期条件

先统计出需要出勤的日期,计算出全部工作小时,再遍历法定节假日数组,剔除法定节假日的工作小时

demo如下:

参考api

节假日api,依据条件进行筛选

数据结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
return {
// 法定节假日
festival: ["2018-12-30", "2018-12-31", "2019-01-01", "2019-02-03", "2019-02-04", "2019-02-05", "2019-02-06", "2019-02-07", "2019-02-08", "2019-02-09",
"2019-02-10", "2019-02-11", "2019-04-05", "2019-04-06", "2019-04-07", "2019-05-01", "2019-05-02", "2019-05-03", "2019-05-04", "2019-06-07", "2019-06-08",
"2019-06-09", "2019-09-13", "2019-09-14", "2019-09-15", "2019-10-01", "2019-10-02", "2019-10-03", "2019-10-04", "2019-10-05", "2019-10-06", "2019-10-07",
"2020-01-01", "2020-01-24", "2020-01-25", "2020-01-26", "2020-01-27", "2020-01-28", "2020-01-29", "2020-01-30", "2020-01-31", "2020-02-01", "2020-02-02",
"2020-04-04", "2020-04-05", "2020-04-06", "2020-05-01", "2020-05-02", "2020-05-03", "2020-05-04", "2020-05-05", "2020-06-25", "2020-06-26", "2020-06-27",
"2020-10-01", "2020-10-02", "2020-10-03", "2020-10-04", "2020-10-05", "2020-10-06", "2020-10-07", "2020-10-08",
"2021-01-01", "2021-02-11", "2021-02-12", "2021-02-13", "2021-02-14", "2021-02-15", "2021-02-16", "2021-02-17", "2021-02-26", "2021-04-02", "2021-04-03",
"2021-04-04", "2021-04-30", "2021-05-01", "2021-05-02", "2021-06-12", "2021-06-13", "2021-06-14", "2021-06-12", "2021-09-19", "2021-09-20", "2021-09-21",
"2021-10-01", "2021-10-02", "2021-10-03", "2021-10-04", "2021-10-05", "2021-10-06", "2021-10-07",
"2022-01-01", "2022-01-31", "2022-02-01", "2022-02-02", "2022-02-03", "2022-02-04", "2022-02-05", "2022-02-06", "2022-04-03", "2022-04-04", "2022-04-05",
"2022-04-30", "2022-05-01", "2022-05-02", "2022-06-03", "2022-06-04", "2022-06-05", "2022-09-09", "2022-09-10", "2022-09-11", "2022-10-01", "2022-10-02",
"2022-10-03", "2022-10-04", "2022-10-05", "2022-10-06", "2022-10-07"
],
//需要上班的周末
weekendWorkDay: ["2018-12-29", "2019-02-02", "2019-09-29", "2019-10-12", "2019-04-28", "2019-05-05",
"2020-01-19", "2020-04-26", "2020-05-09", "2020-06-28", "2020-09-27", "2020-10-10",
"2021-02-07", "2021-02-20", "2021-09-18", "2021-10-09", "2021-10-10"
],
festival_list: [],
weekendWorkDay_list: []
}
响应方法
1
2
3
4
5
6
7
8
9
10
// 将节假日,周末工作日转换为时间戳
this.festival.forEach((i, item) => {
this.festival_list.push(new Date(item).valueOf())
})
this.weekendWorkDay.forEach((i, item) => {
this.weekendWorkDay_list.push(new Date(item).valueOf())
})


this.formatCountDay("2022-07-22", "2022-07-25")
读入数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 过滤俩天之间的周末节假日,返回距离的天数
formatCountDay (start, end) {
var sign = true
var startday = new Date(start)
var endday = new Date(end)

// 总相差天数
var diffDay = (endday - startday) / (1000 * 60 * 60 * 24) + 1
if (parseInt(diffDay) === 0)
return parseInt(diffDay)
// 周末周六天数+节假日
var weekEnds = 0
for (var i = 0; i < diffDay; i++) {
sign = true
// 判断是否是节假日
if (this.festival_list.includes(startday.valueOf())) {
console.log("节假日")
weekEnds = weekEnds + 1
sign = false
}
// 判断周六周日,如果是节假日则不作判断
if (sign === true) {
if (startday.getDay() === 0 || startday.getDay() === 6) {
// 判断该周末是否需要因为节假日补班
var weekEnds_sign = 0
for (var j in this.weekendWorkDay_list) {
if (startday.valueOf() === this.weekendWorkDay_list[j]) {
weekEnds_sign = weekEnds_sign + 1
}
}
if (weekEnds_sign === 0) {
weekEnds = weekEnds + 1
}
}
}
startday.setDate(startday.getDate() + 1)
}
console.log(diffDay - weekEnds)
return parseInt(diffDay - weekEnds)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/**
* 计算请假时长
* @param {Object} beginTime 开始时间
* @param {Object} endTime 结束时间
* @param {Object} stWorkTime 上班时间
* @param {Object} enWrokTime 下班时间
* @param {Object} isFreeTime 是否要去除午休工作时长
* @param {Object} freeTimeMon 午休开始时间
* @param {Object} freeTimeAft 午休结束时间
*
*/
getTotal(beginTime ,endTime,stWorkTime,enWrokTime,isFreeTime,freeTimeMon,freeTimeAft){
var days;
var hours;
var date;
var freeTime=freeTimeAft-freeTimeMon;

beginTime = beginTime.replace(/-/g,'/');
var beginArr = beginTime.split(" ");
var beginMonth = parseInt( beginArr[0].split("/")[1]);
var beginDay = parseInt(beginArr[0].split("/")[2]);
var beginHours = parseInt(beginArr[1].split(":")[0]);
var beginMin = parseInt(beginArr[1].split(":")[1]);
var beginHoursMin = beginHours+beginMin/60;

endTime = endTime.replace(/-/g,'/');
var endArr = endTime.split(" ");
var endMonth = parseInt(endArr[0].split("/")[1]);
var endDay = parseInt(endArr[0].split("/")[2]);
var endHours = parseInt(endArr[1].split(":")[0]);
var endMin = parseInt(endArr[1].split(":")[1]);
var endHoursMin = endHours+endMin/60;


//如果beginHoursMin时间小于上班时间都算上班时间
if (beginHoursMin<=stWorkTime){
beginHoursMin = stWorkTime;
}
//如果endHoursMin时间大于上班时间都算下班时间
if (endHoursMin>=enWrokTime){
endHoursMin = enWrokTime;
}
//如果结束时间在freeTimeMon和freeTimeAft之间都算freeTimeMon
if (isFreeTime==true){
if (endHoursMin>=freeTimeMon && endHoursMin<=freeTimeAft){
endHoursMin = freeTimeMon;
}

}


//获取结束时间-开始时间的天数
var daysBetween = this.daysBetween(beginTime,endTime);
if (daysBetween.length>0){
var daysBetweenLen = daysBetween.length;
//午休
if (isFreeTime==true){
var hour = enWrokTime-stWorkTime-freeTime;
if (daysBetweenLen==1){
//同一天
hours=(endHoursMin)-(beginHoursMin)-freeTime;
}else if (daysBetweenLen==2){
//跨一天
//第一天的时长
hours = enWrokTime - beginHoursMin;
//是否有午休
if (beginHoursMin<=freeTimeMon)
hours=hours-freeTime;
//第二天的时长
hours += endHoursMin -stWorkTime ;
//是否有午休
if (endHoursMin>=freeTimeAft)
hours=hours-freeTime;

}else{
//跨两天以上
//第一天的时长
hours = enWrokTime - beginHoursMin;
//是否有午休
if (beginHoursMin<=freeTimeMon)
hours=hours-freeTime;
//中间时长
hours+=(daysBetweenLen-2)*(hour);
//最后一天时长
hours += endHoursMin -stWorkTime ;
//是否有午休
if (endHoursMin>=freeTimeAft)
hours=hours-freeTime;
}
days = Math.floor(hours/hour);
hours = hours%hour;
date ={"days":days,"hours":hours};

}else{
//非午休
hour = enWrokTime-stWorkTime;
if (daysBetweenLen==1){
//同一天
hours=(endHoursMin)-(beginHoursMin);
}else if (daysBetweenLen==2){
//跨一天
hours = enWrokTime - beginHoursMin;
//第二天的时长
hours += endHoursMin -stWorkTime ;
}else{
//跨两天以上
//第一天的时长
hours = enWrokTime - beginHoursMin;
//中间时长
hours+=(daysBetweenLen-2)*(hour);
//最后一天时长
hours += endHoursMin -stWorkTime ;
}
days = Math.floor(hours/hour);
hours = hours%hour;
date ={"days":days,"hours":hours};
}


}
console.log(date)
return date;
},
/**
* 根据两个日期,判断相差天数
* @param sDate1 开始日期 如:2016-11-01
* @param sDate2 结束日期 如:2016-11-02
* @returns {number} 返回相差天数
*/
daysBetween(sDate1,sDate2){
var arr = [];
sDate1 = sDate1.substring(0,10);
sDate2 = sDate2.substring(0,10);
var startTime = this.gDate(sDate1);
var endTime = this.gDate(sDate2);
while((endTime.getTime()-startTime.getTime())>=0){
var year = startTime.getFullYear();
var month = startTime.getMonth().toString().length==1?"0"+startTime.getMonth().toString():startTime.getMonth();
var day = startTime.getDate().toString().length==1?"0"+startTime.getDate():startTime.getDate();
arr.push(year+"/"+month+"/"+day);
startTime.setDate(startTime.getDate()+1);
}
return arr;

},

gDate(datestr){
datestr=datestr.replace(/-/g,'/');
var temp = datestr.split("/");
var date = new Date(temp[0],temp[1],temp[2]);
return date;
},

//函数调用
this.getTotal('2022-08-27 09:00:00' ,'2022-08-28 18:00:00',9,18,false,12,13.5)