fix(工时): 按中国工作日历统计正常耗时

This commit is contained in:
Script Generator
2026-06-29 15:04:32 +08:00
parent 47f41c3e40
commit aa6970876a
5 changed files with 51 additions and 14 deletions

View File

@@ -1,3 +1,5 @@
import { isChinaWorkday } from './china-workday-calendar';
export const WORK_HOURS = {
morningStart: 9,
morningEnd: 12,
@@ -27,7 +29,7 @@ function dayBound(d: Date, hourFloat: number): Date {
}
function dayOverlapHours(start: Date, end: Date, day: Date): number {
if (WORK_HOURS.skipWeekends && isWeekend(day)) return 0;
if (WORK_HOURS.skipWeekends && !isChinaWorkday(day)) return 0;
const morningStart = dayBound(day, WORK_HOURS.morningStart);
const morningEnd = dayBound(day, WORK_HOURS.morningEnd);
const afternoonStart = dayBound(day, WORK_HOURS.afternoonStart);
@@ -55,7 +57,7 @@ function dayOverlapHours(start: Date, end: Date, day: Date): number {
* - 全在周末 周六全天 = 0h
* - 负区间 / 非法 ISO = 0
*/
export function calcWorkHours(startISO: string, endISO: string): number {
function calcWorkHoursRaw(startISO: string, endISO: string): number {
if (!startISO || !endISO) return 0;
const start = new Date(startISO);
const end = new Date(endISO);
@@ -73,6 +75,11 @@ export function calcWorkHours(startISO: string, endISO: string): number {
cursor.setDate(cursor.getDate() + 1);
}
return total;
}
export function calcWorkHours(startISO: string, endISO: string): number {
const total = calcWorkHoursRaw(startISO, endISO);
return Math.round(total * 2) / 2;
}
@@ -100,12 +107,11 @@ export function formatWorkHoursShort(hours: number): string {
* 用于“实际耗时”口径:按开始/结束时间戳直接相减,精度 0.5h
* 只要有正向耗时,最低按 0.5h 计,避免 30 分钟内工作被显示为 0。
*/
// 实际耗时只统计中国工作日历内的工作时段;加班通过 overtime 记录单独计入。
export function calcActualElapsedHours(startISO?: string | null, endISO?: string | null): number {
if (!startISO || !endISO) return 0;
const start = new Date(startISO).getTime();
const end = new Date(endISO).getTime();
if (isNaN(start) || isNaN(end) || end <= start) return 0;
const hours = (end - start) / MS_PER_HOUR;
const hours = calcWorkHoursRaw(startISO, endISO);
if (hours <= 0) return 0;
return Math.max(0.5, Math.round(hours * 2) / 2);
}
@@ -146,7 +152,7 @@ export function addWorkHours(startISO: string, hours: number): string {
while (remaining > 0) {
const day = new Date(cursor);
day.setHours(0, 0, 0, 0);
if (WORK_HOURS.skipWeekends && isWeekend(day)) {
if (WORK_HOURS.skipWeekends && !isChinaWorkday(day)) {
cursor.setDate(cursor.getDate() + 1);
cursor.setHours(WORK_HOURS.morningStart, 0, 0, 0);
continue;