记工时总算不明白,写了个打卡计算器,录上下班自动算加班
每个月填工时表都让我头大。公司要的是"实际在岗工时"和"加班时长"两栏,可我脑子里只有"早上九点半到、晚上七点走"这种模糊印象。拿计算器按半天,午休扣不扣、夜班跨不跨天还各有说法,月底一汇总经常对不上。后来干脆写了个网页小工具:录上上下班时间,工时和加班一键出来,每天记一笔,月底直接看总和。整个东西纯前端,数据丢在浏览器 localStorage,不上传任何服务器。
一、先把时间变成能算的数字
输入框里是 “09:30” 这种字符串,没法直接相减。第一步把它拆成小时和分钟,换算成"从零点到现在过了多少分钟":
function toMin(t) {
const [h, m] = t.split(':').map(Number);
return h * 60 + m;
}
这样 09:30 变成 570,18:30 变成 1110,两者一减就是 540 分钟,也就是 9 小时整。比拿字符串硬算省事太多,后面所有逻辑都建立在"分钟数"这个整数上。
二、工时和加班怎么算
标准工时按 8 小时(480 分钟)算,超出的部分算加班。但午休这段要不要扣,不同公司做法不一样,我把它做成可选项:
function calc(start, end, breakMin = 0) {
let work = toMin(end) - toMin(start) - breakMin;
if (work < 0) work += 24 * 60; // 跨午夜班次兜底
const overtime = Math.max(0, work - 480);
return { work, overtime };
}
work < 0 这条是给夜班准备的:23:00 上到次日 07:00,直接减是负数,加上一天 1440 分钟就回到正数了。Math.max(0, ...) 保证不出现负加班。扣不扣午休,只影响 breakMin 这一个参数,核心算法不动。
三、每天记下来按月看
单次算完就丢没意义,得存住。用日期当 key 写进 localStorage,月底把整月筛出来:
const key = '2026-09-16';
const log = JSON.parse(localStorage.getItem('worklog') || '{}');
log[key] = { start: '09:30', end: '19:00', breakMin: 60 };
localStorage.setItem('worklog', JSON.stringify(log));
// 月底汇总
const month = '2026-09';
let totalWork = 0, totalOt = 0;
for (const [day, r] of Object.entries(log)) {
if (day.startsWith(month)) {
const c = calc(r.start, r.end, r.breakMin);
totalWork += c.work; totalOt += c.overtime;
}
}
渲染时把当月每天的工时、加班分别求和,再除以 60 转成"X 小时",一眼就能看出这个月加了多少班。
| 是否扣午休 | 09:30–19:00 结果 | 适合场景 |
|---|---|---|
| 不扣(breakMin=0) | 工时 570 分(9.5h),加班 90 分 | 弹性工时、午休也在岗 |
| 扣 60 分 | 工时 510 分(8.5h),加班 30 分 | 午休离岗、严守坐班 |
几个坑
- 用户手输 “9:30” 没补零,
split后Number('9')能正常算,但回显时要padStart(2,'0')补齐,不然表格里的 9:30 和 09:30 混着看很乱。 - 跨午夜只加了一次 1440,连续上两天班(极少)会算错,普通打卡用不到,没特殊处理。
- localStorage 读出来一定是字符串,忘了
JSON.parse直接当对象用,会得到[object Object],调试半天才发现。 - 加班标准写死 480 分钟,有的公司按 21:00 后算加班,这种得把阈值也做成配置,别硬编码进公式。
小结
打卡计算器的核心就一句话:把时间统一成分钟数,减法解决一切。午休、跨天、加班标准这些差异,都是挂在 breakMin 和那个 480 常量上的可调参数。再配合 localStorage 把每天的结果落盘,月底汇总就是遍历一遍对象的事。整个工具不到一百行,却把我每月最烦的填表活儿彻底省了。
- 点赞
- 收藏
- 关注作者
评论(0)