{
  "schemaVersion": 1,
  "slug": "time-card-calculator",
  "category": "date-time",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "eee7338ae3f5ab8ed49a38b0a89fbc73d616a1e208856677e655f366e0f9e009",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/time-card-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "H = Σ hᵢ; P = R × min(H,T) + R × k × max(H−T,0)",
    "vars": [
      [
        "H",
        "Weekly hours"
      ],
      [
        "hᵢ",
        "Hours per day (Mon–Fri)"
      ],
      [
        "R",
        "Hourly rate"
      ],
      [
        "T",
        "Overtime threshold"
      ],
      [
        "k",
        "Overtime multiplier"
      ]
    ],
    "note": "Each day entry is parsed as hours + minutes ÷ 60."
  },
  "externalEvidence": {
    "reviewedAt": "2026-10-12",
    "sources": [
      {
        "name": "US Department of Labor — Hours worked and overtime under the FLSA",
        "url": "https://www.dol.gov/agencies/whd/fact-sheets/22-flsa-hours-worked"
      }
    ],
    "referenceRole": "context",
    "implementationHash": "eee7338ae3f5ab8ed49a38b0a89fbc73d616a1e208856677e655f366e0f9e009",
    "basis": "H = Σ hᵢ; P = R × min(H,T) + R × k × max(H−T,0)",
    "limitations": "The references provide context and limitations. They do not validate this page’s illustrative multipliers, lookup values or predictions."
  },
  "contract": {
    "compute": "const parse=(s)=>{const raw=String(s).trim();if(raw==='')return 0;const m=/^(\\d{1,2}):(\\d{2})$/.exec(raw);if(!m)return null;const h=+m[1],mi=+m[2];if(h>24||mi>59||(h===24&&mi!==0))return null;return h+mi/60;}; const days=[monday,tuesday,wednesday,thursday,friday].map(parse); if(days.some(v=>v===null)) return { totalHours: null, regularHours: null, overtimeHours: null, grossPay: null, dailyAverage: null, __error: 'inputError' }; const total=days.reduce((a,b)=>a+b,0); const regular=Math.min(total,overtimeAfter); const ot=Math.max(total-overtimeAfter,0); return {totalHours:total,regularHours:regular,overtimeHours:ot,grossPay:regular*hourlyRate+ot*hourlyRate*overtimeMultiplier,dailyAverage:total/5};",
    "inputs": [
      {
        "name": "monday",
        "type": "text",
        "default": "08:00",
        "step": 1
      },
      {
        "name": "tuesday",
        "type": "text",
        "default": "08:00",
        "step": 1
      },
      {
        "name": "wednesday",
        "type": "text",
        "default": "08:00",
        "step": 1
      },
      {
        "name": "thursday",
        "type": "text",
        "default": "08:00",
        "step": 1
      },
      {
        "name": "friday",
        "type": "text",
        "default": "08:00",
        "step": 1
      },
      {
        "name": "hourlyRate",
        "type": "number",
        "default": 25,
        "min": 0,
        "max": 10000,
        "step": 0.25
      },
      {
        "name": "overtimeAfter",
        "type": "number",
        "default": 40,
        "min": 0,
        "max": 168,
        "step": 1,
        "slider": true
      },
      {
        "name": "overtimeMultiplier",
        "type": "number",
        "default": 1.5,
        "min": 1,
        "max": 3,
        "step": 0.1,
        "slider": true
      }
    ],
    "outputs": [
      {
        "name": "totalHours",
        "precision": 2,
        "unit": "h"
      },
      {
        "name": "regularHours",
        "precision": 2,
        "unit": "h"
      },
      {
        "name": "overtimeHours",
        "precision": 2,
        "unit": "h"
      },
      {
        "name": "grossPay",
        "precision": 2,
        "unit": "$"
      },
      {
        "name": "dailyAverage",
        "precision": 2,
        "unit": "h"
      }
    ],
    "interpret": null
  }
}
