js工时计算函数
- 实例是把工作时间、工作一整天工作工时、休息时间都写死的,感兴趣的话可以自己通过参数传进来,自行修改。
- 使用的工具库 dayjs
- 导入:import { workingHours } from “代码存放路径”
- 使用:workingHours('2024-10-01 00:00:00', '2024-10-07 23:59:59') 会返回总工时秒数,用一个参数接一下就ok了。
import dayjs from 'dayjs'
const workHours = [
{ start: '08:00', end: '11:20' },
{ start: '12:50', end: '17:30' },
{ start: '18:00', end: '20:30' }
]
const normalWorkTime = 28800
const overtimeWorkTime = 37800
const breaks: any = [{ start: '10:00', end: '10:15' }]
export const workingHours = (start: string, end: string, type: boolean = false) => {
start = dayjs(start).format('YYYY-MM-DD HH:mm:ss')
end = dayjs(end).format('YYYY-MM-DD HH:mm:ss')
const startDate = start.split(' ')[0]
const endDate = end.split(' ')[0]
let dates = getDatesBetween(startDate, endDate)
let totalSeconds = 0;
if (dates.length == 1) {
totalSeconds = computedSecond(start, end)
}
if (dates.length >= 2) {
let baseTime = normalWorkTime
const firstStartTime = start
let firstEndTime = start.split(' ')[0] + ' ' + workHours[1].end
let afterStartTime = end.split(' ')[0] + ' ' + workHours[0].start
const afterEndTime = end
if (type) {
baseTime = overtimeWorkTime
firstEndTime = start.split(' ')[0] + ' ' + workHours[2].end
afterStartTime = end.split(' ')[0] + ' ' + workHours[0].start
}
const s1 = computedSecond(dayjs(firstStartTime), dayjs(firstEndTime))
const s2 = computedSecond(dayjs(afterStartTime), dayjs(afterEndTime))
if (dates.length == 2) {
totalSeconds = s1 + s2
} else {
const newDates = dates.slice(1, dates.length - 1)
const sundayNubers = countSundays(newDates)
let totalRestSeconds = 0;
breaks.forEach(({ start, end }: any) => {
const startDate = new Date();
const parts = start.split(':');
startDate.setHours(parseInt(parts[0]), parseInt(parts[1]), 0, 0);
const endDate = new Date();
const endParts = end.split(':');
endDate.setHours(parseInt(endParts[0]), parseInt(endParts[1]), 0, 0);
const diffInMs = endDate.getTime() - startDate.getTime();
totalRestSeconds += diffInMs / 1000;
});
totalSeconds = s1 + s2 + (dates.length - 2 - sundayNubers) * (baseTime - totalRestSeconds)
}
}
return totalSeconds > 0 ? totalSeconds : 0
}
const getDatesBetween = (startDateStr: string, endDateStr: string) => {
const startDate = new Date(startDateStr);
const endDate = new Date(endDateStr);
let dates: string[] = [];
if (endDate < startDate) return dates
let currentDate = new Date(startDate);
while (currentDate <= endDate) {
let formattedDate = currentDate.getFullYear() + '-' +
(currentDate.getMonth() + 1).toString().padStart(2, '0') + '-' +
currentDate.getDate().toString().padStart(2, '0');
dates.push(formattedDate);
currentDate.setDate(currentDate.getDate() + 1);
}
return dates;
}
const computedSecond = (start: string | dayjs.Dayjs, end: string | dayjs.Dayjs) => {
let total = 0
const startDate = dayjs(start)
const endDate = dayjs(end)
for (const { start, end } of workHours) {
const workStart = dayjs(startDate.format('YYYY-MM-DD') + 'T' + start);
const workEnd = dayjs(startDate.format('YYYY-MM-DD') + 'T' + end);
if (workStart.isAfter(endDate) || workEnd.isBefore(startDate)) {
continue;
}
const overlapStart = workStart.isAfter(startDate) ? workStart : startDate;
const overlapEnd = workEnd.isBefore(endDate) ? workEnd : endDate;
let overlapDuration = overlapEnd.diff(overlapStart, 'second');
for (const { start: breakStart, end: breakEnd } of breaks) {
const breakStartTime = dayjs(overlapStart.format('YYYY-MM-DD') + 'T' + breakStart);
const breakEndTime = dayjs(overlapStart.format('YYYY-MM-DD') + 'T' + breakEnd);
if (breakStartTime.isAfter(overlapEnd) || breakEndTime.isBefore(overlapStart)) {
continue;
}
const overlapBreakStart = breakStartTime.isAfter(overlapStart) ? breakStartTime : overlapStart;
const overlapBreakEnd = breakEndTime.isBefore(overlapEnd) ? breakEndTime : overlapEnd;
overlapDuration -= overlapBreakEnd.diff(overlapBreakStart, 'second');
}
total += overlapDuration;
}
return total
}
const countSundays = (dates: string[]) => {
let sundayCount = 0;
for (let i = 0; i < dates.length; i++) {
const date = new Date(dates[i]);
if (date.getDay() === 0) {
sundayCount++;
}
}
return sundayCount;
}