Skip to content

About

Time card, overtime and hours math with no dependencies. The engine behind hourtotal.com.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hourtotal-calc

The time card and overtime math behind HourTotal, as one dependency-free ES module. Everything the calculators do to a week of clock times happens in calc.js; the site adds the grid, the print sheet and the CSV on top.

What it does

  • Parse typed clock times: 8, 830, 8:30, 5p, 1730, noon all resolve to minutes since midnight. An end time earlier than its start is read as the next day.
  • Compute a day: two punch pairs per day, an unpaid break in minutes, optional rounding of the daily total to 6 or 15 minutes.
  • Split overtime under four rules: none, federal weekly 40, daily 8 plus weekly 40, and California (8/12 daily, seventh-day). Hours already counted as daily overtime never count toward the weekly 40.
  • Price a week: regular, 1.5x and 2x pay from a split and an hourly rate.
  • Utilities: hours between two times, add or subtract a duration from a clock time, sum a list of signed durations, decimal hours to hh:mm, 12-hour and 24-hour formatting.

Usage

import { computeDay, splitOvertime, pay, toHHMM } from "./calc.js";

const week = [
  { in1: "7:05", out1: "12:10p", in2: "2p", out2: "6:35p" },
  { in1: "7", out1: "3:30p" },
  { in1: "7:10", out1: "3:25p" },
  { in1: "6:50", out1: "5:45p" },
  { in1: "7", out1: "1p" },
];
const minutes = week.map((d) => computeDay(d, { roundStep: 0 }).minutes);
const split = splitOvertime(minutes, "weekly40");   // { regular: 2400, ot15: 200, ot20: 0 }
const p = pay(split, 16.5);                          // { regular: 660, ot15: 82.5, ot20: 0, gross: 742.5 }
console.log(toHHMM(minutes.reduce((a, b) => a + b))); // "43:20"

Run the tests with npm test (Node 18 or later, no install step).

API

Function Purpose
parseTime(raw, assume) Typed time to minutes since midnight, or null. assume is "am", "pm" or null for a bare hour.
resolveDay(entry) Pairs in1/out1/in2/out2, infers AM/PM for a bare end time, reports error or empty.
computeDay(entry, { roundStep }) Minutes worked in a day after the break, with overnight flag.
roundMinutes(minutes, step) Nearest-step rounding, 0 for exact.
splitOvertime(dayMinutes[], rule) regular, ot15, ot20 minutes for "none", "weekly40", "daily8" or "california".
pay(split, rate) Regular, overtime, double-time and gross pay.
hoursBetween(start, end, breakMin) Duration between two clock times.
addDuration(time, hours, minutes, sign) Clock time after adding or subtracting a duration, with day offset. A time typed without AM/PM is read on a 24-hour clock, so 12:30 is noon.
sumDurations(rows) Total minutes of [{ sign, h, m }], minutes over 59 carry.
toHHMM, toDecimal, decimalToHHMM, to12h, toMilitary Formatting helpers.

Where it is used

The overtime rules follow the U.S. Department of Labor's FLSA guidance and California's Labor Code; the overtime rules by state page lists the primary sources. This is arithmetic, not legal advice.

License

MIT. Copyright 2026 Raptune Limited.

About

Time card, overtime and hours math with no dependencies. The engine behind hourtotal.com.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages