Interval resolution, stage 1 of the calculation pipeline

Featurekamo-shared-library
Shipped
August 11, 2026 at 11:47 PM UTC
Author
Kamo
Commit
abedbab

Punches become resolved spans. Pure, total, and over value types rather than entities so every stage is fixture-testable with no persistence context. Durations come from Duration.between on instants, never wall-clock subtraction. That is the entire DST story and the tests pin it: a 22:00-06:00 shift is SEVEN hours across spring-forward and NINE across fall-back. Subtracting wall clocks computes 8 for both -- one underpaying, one overpaying, and in a daily-overtime jurisdiction the 9-hour night silently loses its overtime hour. Anything unpairable comes back as unresolved rather than guessed. An unclosed shift is an EXCEPTION: leaving it open accrues absurd hours, auto-closing at a scheduled end under-reports, and a fixed cap invents a number nobody witnessed. It must never finalize as zero -- that pays nothing for a day that was worked. Meals are punched, never auto-deducted. TRANSFER closes one span and opens the next without ending the shift, so meal timing and shift-length eligibility continue across a mid-shift move between cost centres.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing