Hours calculator
Clock in at 09:00, clock out at 17:30, take a 30-minute lunch, and you worked exactly 8 hours. Enter the start time, end time and unpaid break minutes for one day and get the decimal hours your timesheet or invoice needs. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Start time
- 09:00
- End time
- 17:30
- Break minutes
- 30
- Start time
- 09:00:00
- End time
- 17:30:00
- Elapsed minutes
- 510
- Elapsed hours
- 8.5
Knowing how many hours you actually worked is a payroll and timesheet chore, not a calendar puzzle. You clock in at a start time, clock out at an end time, subtract unpaid lunch or other break minutes, and convert the remainder into decimal hours for a timesheet, invoice, or wage line. This hours calculator does exactly that: it reads a start clock and an end clock on the same civil day, subtracts non-negative break minutes, and returns the net duration in hours. It is not a date-difference tool, not an overtime-pay estimator, and not a clock-plus-hours adder.
What hours worked between two clocks actually means
Hours worked on a single day is elapsed clock time minus unpaid breaks, written as a decimal hour count. Convert the start clock and the end clock to minutes after midnight, subtract those totals, subtract break minutes, then divide by sixty. Nine o'clock to seventeen thirty is five hundred ten elapsed minutes; a thirty-minute lunch leaves four hundred eighty minutes, which is exactly eight hours.
That eight is what a timesheet cell, an invoice line, and most payroll systems store. The same identity is what people mean when they search for an hours calculator: not a conversion between weeks and seconds, not adding five hours onto a clock face, and not the signed gap between two ISO datetimes on different calendar days. Overnight rotas belong to a roster tool that also knows the next calendar date.
Negative break minutes are rejected because a break cannot add time to the shift. Breaks that last longer than the punch interval are also rejected, so the result is never a negative duration.
Where an hours-worked calculator earns its keep
Hourly staff and contractors turn a paper punch pair into the decimal hours a payroll export expects, after lunch is removed, without opening a spreadsheet. Freelancers convert a studio block into billable hours for an invoice line that must match the timesheet the client already signed. Shift leads check that a planned start and finish minus a mandated rest still equals the contracted day length before they post the roster.
Tutors and exam-prep sites need a deterministic oracle that marks 09:00 to 17:30 minus thirty minutes as eight hours, not as eight and a half, and that fails a reversed pair instead of silently wrapping past midnight. Pair this calculator with an overtime-pay tool when you already know the extra hours and the rate, and with a salary converter when you need annual pay from an hourly wage.
What you can do with it
Timesheet and payroll punch pairs
Turn a same-day clock-in, clock-out, and lunch into decimal hours that a payroll export or wage line can store without a spreadsheet.
Freelance invoices and studio blocks
Convert a booked start and finish minus an unpaid pause into billable hours that match the timesheet the client already signed.
FAQ
Can break minutes be zero, omitted, or a fraction?
Fractional minutes are allowed. Negative breaks and breaks longer than the elapsed punch are rejected.
Which clock formats does the hours calculator accept?
Twenty-four-hour HH:MM or HH:MM:SS from 00:00 to 23:59, and twelve-hour clocks with AM or PM.
What if my shift runs past midnight?
This calculator handles same-day shifts only. An end time earlier than the start time is refused instead of being wrapped into the next day, so for overnight rotas use a roster tool that also knows the next calendar date.
How are minutes turned into decimal hours?
The net minutes are divided by sixty. From 08:15 to 16:45 with a 45-minute break you worked 7.75 hours, because those 45 minutes count as three quarters of an hour, not as 45 hundredths.
Does it work out overtime pay?
No. It only returns the hours worked after breaks. When you already know the extra hours and the rate, use an overtime-pay tool, and use a salary converter if you need annual pay from an hourly wage.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/life/hours \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"start_time":"09:00","end_time":"17:30"}'const res = await fetch("https://api.kit.forhosting.com/life/hours", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"start_time": "09:00",
"end_time": "17:30"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/life/hours",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"start_time": "09:00",
"end_time": "17:30"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/life/hours", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"start_time":"09:00","end_time":"17:30"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"start_time":"09:00","end_time":"17:30"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/life/hours", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"start_time": "09:00",
"end_time": "17:30"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "life.hours",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_break_minutes | 100000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
If the end clock precedes the start clock, or if break minutes are negative, the task fails with invalid_input and is not billed. Successful API calls use the published $0.002 base price.
What hours worked between two clocks actually means
This endpoint refuses an end clock that precedes the start clock instead of inventing an overnight wrap, because the search intent is a same-day punch pair.
Input contract, response shape, and error behaviour
Example: 08:15 to 16:45 minus 45 minutes yields hours 7.75. Missing clocks, a face such as 25:00 or 9:70, an end that precedes the start, a negative break, or a break longer than the punch are typed failures and are not billed. POST a JSON body with two required clock strings and an optional break. start_time is the clock-in face: twenty-four-hour HH:MM or HH:MM:SS from 00:00 to 23:59, or a twelve-hour clock with AM or PM such as 9:00 AM. Aliases start, from, and clock_in are accepted so spreadsheets and typed forms can reuse the same contract. end_time is the clock-out face in the same formats; aliases end, to, and clock_out are accepted. break_minutes is a non-negative finite number of unpaid minutes to subtract; omit it or send 0 for a continuous block. Aliases breaks, break, and lunch are accepted. Integers, decimals, scientific notation, and numeric strings all parse for the break; booleans, arrays, objects, Infinity, and NaN fail with invalid_input naming break_minutes. On success the body echoes the normalized twenty-four-hour start_time and end_time, the parsed break_minutes, elapsed_minutes and elapsed_hours before the break, net minutes, the primary hours value, net seconds, hours_hms as HH:MM:SS, and a short formula string. Example: start_time 09:00, end_time 17:30, break_minutes 30 yields hours 8 and hours_hms 08:00:00.
Where an hours-worked calculator earns its keep
On this page the work runs entirely in your browser; through the API each successful punch costs $0.002, failed validation is not charged, and nothing is stored after the response returns.
Integration use cases
Roster checks and exam keys
Assert that a planned shift minus rest equals the contracted day, and pin golden hours values in fixtures that must not depend on the machine clock.
Technical questions
How do I calculate hours worked between two times?
Send start_time and end_time as clock strings (09:00, 17:30:00, or 5:30 PM) and optional break_minutes. The API returns hours as a decimal duration after the unpaid break is subtracted.
What if the end time is earlier than the start time?
The task fails with invalid_input. This calculator is a same-day punch pair: an end that precedes the start is not treated as an overnight wrap.
What does the hours calculator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.