通用加班工时计算器(参数化版)
帮用户从打卡记录算月度加班时长。规则参数可配置,适配不同公司制度。
一、什么时候用
- 用户给考勤截图 / 打卡记录,要算加班
- 用户问"这个月加了多少小时班"
- 需要按法定节假日、调休区分档位计算
二、默认规则(可改,见第六节)
档位判定(优先级从高到低)
| 优先级 | 类型 | 归入 |
|---|---|---|
| 1 | 调休工作日(国务院公告要上班的周六日) | 工作日档 |
| 2 | 法定节假日 | 节假日档 |
| 3 | 普通周六 / 周日 | 节假日档 |
| 4 | 其余 周一~周五 | 工作日档 |
> 一句话:节假日 = 法定节假日 + 周六日 − 调休;工作日 = 其余周一~周五 + 调休的周末
工作日档
- 用打卡时长(默认不扣午休)
- 工时 < 11.5h → 加班 0
- 工时 ≥ 11.5h →
加班 = (floor((工时 − 11.5) / 0.5) + 1) × 0.5
| 工时区间 | 加班 |
|---|---|
| < 11.5h | 0 |
| [11.5, 12) | 0.5h |
| [12, 12.5) | 1.0h |
| [12.5, 13) | 1.5h |
| [13, 13.5) | 2.0h |
节假日档
- 先扣 12:00~13:00 午休,用有效工时判定
有效工时 = 打卡时长 − 与午休时段的重叠(部分覆盖按实际重叠算)- 有效工时 ≥ 8h → 加班 8h
- 有效工时 ∈ [4h, 8h) → 加班 4h
- 有效工时 < 4h → 加班 0
典型场景(已内置自检):
| 打卡 | 时长 | 扣午休 | 有效 | 加班 |
|---|---|---|---|---|
| 12:30–21:00 | 8.5h | −0.5h | 8.0h | 8h |
| 13:00–21:00 | 8.0h | −0 | 8.0h | 8h |
| 10:00–15:00 | 5.0h | −1.0h | 4.0h | 4h |
| 08:00–12:00 | 4.0h | −0 | 4.0h | 4h |
> 注意:13 点后才上班的日子,8h 打卡就够满档(不覆盖午休)。
三、特殊情况
- 出差 / 外勤:不影响档位判定,但无打卡 → 加班 0
- 事假 / 年假:有打卡按正常规则算;无打卡则 0
- 当天仍在进行中(只有上班没有下班时间):跳过不计
- 跨天打卡:下班 < 上班时,下班时间 +24h;午休重叠会同时检查第二天
四、执行步骤
- 读取打卡数据(从截图识别,或用户直接提供)
- 确定该月法定节假日和调休上班日
- 2026 年直接用内置表(见第五节)
- 其他年份 / 不确定时 → WebSearch 查国务院办公厅公告,别靠推算 - 逐日判定档位 → 算加班
- 务必双路交叉验证:Python 脚本 + Node 各跑一遍,结果必须一致
- 输出表格:日期 / 星期 / 档位 / 打卡h / 午休 / 有效h / 加班 + 两档小计 + 总计
五、2026 年法定节假日与调休(已核实)
来源:https://www.gov.cn/govweb/yaowen/liebiao/202511/content_7047099.htm
| 节日 | 法定假日 | 调休上班日 |
|---|---|---|
| 元旦 | 1/1(四)–1/3(六) | 1/4(日) |
| 春节 | 2/15(日)–2/23(一) | 2/14(六)、2/28(六) |
| 清明 | 4/4(六)–4/6(一) | 无 |
| 劳动节 | 5/1(五)–5/5(二) | 5/9(六) |
| 端午 | 6/19(五)–6/21(日) | 无 |
| 中秋 | 9/25(五)–9/27(日) | 无 |
| 国庆 | 10/1(四)–10/7(三) | 9/20(日)、10/10(六) |
8 月无任何全国法定节假日、无调休 → 所有周六日走节假日档。
六、如何改成你公司的规则
编辑 overwork_calculator.py 顶部的 CONFIG:
CONFIG = {
# 工作日档
"workday_threshold": 11.5, # 起算工时
"workday_step": 0.5, # 档位步长
"workday_step_ot": 0.5, # 每档加班数
# 午休(节假日档默认扣除)
"lunch_start": "12:00:00",
"lunch_end": "13:00:00",
"workday_deduct_lunch": False, # 改 True 则工作日也扣午休
# 节假日档(按有效工时)
"rest_full_hours": 8.0, # 满档门槛
"rest_full_ot": 8.0, # 满档加班数
"rest_half_hours": 4.0, # 半档门槛
"rest_half_ot": 4.0, # 半档加班数
}
HTML 版本的对应参数在 <script> 顶部:nonHolOT() 里的 11.5、holOT() 里的 8 / 4、LUNCH_START / LUNCH_END。
改完参数后,自检用例的期望值要同步调整。
七、自带文件
| 文件 | 用途 |
|---|---|
overwork_calculator.py |
命令行计算,内置 self_test() 自检 8 个典型场景 |
overwork_calculator.html |
可视化日历工具,浏览器直接打开,数据存 localStorage |
核心函数:
def lunch_overlap(start, end, cfg=None): # 与午休时段的重叠小时数
ls, le = _sec(cfg["lunch_start"]), _sec(cfg["lunch_end"])
s, e = _sec(start), _sec(end)
if e <= s: e += 86400
total = 0.0
for base in (0, 86400): # 跨天时第二天午休也算
os_, oe = max(s, ls+base), min(e, le+base)
if oe > os_: total += (oe - os_) / 3600
return total
def restday_overtime(start, end, cfg=None): # 节假日: 扣午休后判有效工时
eff = effective_hours(start, end, cfg)
if eff >= cfg["rest_full_hours"]: return cfg["rest_full_ot"], eff
if eff >= cfg["rest_half_hours"]: return cfg["rest_half_ot"], eff
return 0.0, eff
def workday_overtime(start, end, cfg=None): # 工作日: 默认用打卡时长
h = (effective_hours(start, end, cfg) if cfg["workday_deduct_lunch"]
else duration_hours(start, end))
if h < cfg["workday_threshold"]: return 0.0, h
units = int((h - cfg["workday_threshold"]) / cfg["workday_step"]) + 1
return units * cfg["workday_step_ot"], h
八、易错点
- ❌ 别用"打卡时长 ≥ 9h"判节假日满档 —— 要先扣午休,门槛是有效工时 8h
- ❌ 别漏掉"13 点后才上班"的情况 —— 这类日子不覆盖午休,8h 就够满档
- ❌ 别把午休时段写死 —— 有的公司是 12:00–13:30,必须可配置
- ❌ 调休日的优先级最高 —— 公告要上班的周六日必须算工作日
- ✅ 换年份一定要重查国务院公告,不要外推
- ✅ 算完 Python + Node 双路验证