Time Card / Hours Calculator

Paste a list of shift rows — one per line, with the day, start time, end time, optional break minutes, and optional label — and see per-day totals, per-week totals, and overtime against a configurable daily and weekly threshold. Live, in your browser, nothing is uploaded.

Overtime policy

Daily OT: anything over the daily threshold. Weekly OT: any regular minutes over the weekly threshold. Set a threshold to 0 to disable that kind of OT.

h/day
h/week

Shifts

One shift per line, comma-separated: day, start, end, break, label. Accepts 9:00, 09:00, 21:30, 9 AM, 9pm. Break is in minutes. The day label is free text — Mon, 2026-06-26, Day 1, anything that repeats consecutively for multi-shift days.

Total worked 0h 00m
Regular 0h 00m Within thresholds
Daily OT 0h 00m
Weekly OT 0h 00m

Daily totals

Day Shifts Worked Regular Daily OT Labels
Add a shift to begin.

Weekly totals

Week Span Regular Weekly OT Daily OT Total
Add a shift to begin.

How it works

Row format
One shift per line, comma (or semicolon / pipe / tab) separated. The first three columns are required (day, start, end); the break (in minutes) and a free-text label are optional. A shift whose end is earlier than start is treated as a next-day rollover and surfaced with a (+1d) hint.
Daily OT
Each shift contributes its worked minutes to the day. Up to daily threshold count as regular; the rest count as daily OT. A 10-hour shift under an 8-hour threshold is 8h regular + 2h daily OT.
Weekly OT
After per-day attribution, the week's regular total is capped at weekly threshold. Anything over is reclassified as weekly OT. Daily OT is not touched — a 45-hour week with daily OT does not also generate weekly OT.
Week boundary
A new week starts whenever the same day label appears again after at least one other day has been seen — e.g. Mon…Fri, Mon, Tue is two weeks. This matches the way a hand-written timesheet works and avoids the calendar-arithmetic complexity of looking up the actual week number for free-text day labels.
Time formats
9, 9:00, 09:00, 21:30, 9 AM, 9pm, 12:30 AM, 09:00:45 (seconds discarded) — all accepted. Whitespace is ignored.
Export
Copy TSV writes a tab-separated table: per-shift rows, then per-day totals, then per-week totals, then a grand-total line. Download JSON writes the full structured summary (minutes throughout). Copy summary writes a human-readable paragraph that fits in an email.
Privacy
Everything runs in this tab. No shift data is sent anywhere; the page works offline once loaded.