Interval intersection
Enter two time ranges and get the part they share: 10:00 to 12:00 and 11:00 to 13:00 UTC overlap from 11:00 to 12:00, exactly one hour. Ranges that only touch give an empty result. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Start of interval A
- 2020-01-01T10:00:00.000Z
- End of interval A
- 2020-01-01T12:00:00.000Z
- Start of interval B
- 2020-01-01T11:00:00.000Z
- End of interval B
- 2020-01-01T13:00:00.000Z
- Intersection start
- 2020-01-01T11:00:00.000Z
- Intersection end
- 2020-01-01T12:00:00.000Z
- Intersection duration (milliseconds)
- 3,600,000
- Intersection duration (hours)
- 1
Compute the overlap of two ISO time intervals with strict ordering, duration in milliseconds and hours. Free, deterministic, private in your browser.
What the overlap of two time ranges means
Two time ranges overlap when there is a stretch of time that belongs to both. Think of two meeting room bookings, or two incident windows on a support dashboard: the question is not how long each one lasts, but which part they share. The rule is short. The shared slice begins at the later of the two starts and ends at the earlier of the two ends. If that start comes strictly before that end, the ranges overlap and you get the slice with its length in milliseconds and in hours. For 10:00 to 12:00 and 11:00 to 13:00 UTC, the overlap runs from 11:00 to 12:00, exactly one hour.
Edge cases that trip people up
Ranges that only touch, such as one ending at 12:00 and the next starting at 12:00, share no time, because each end is treated as exclusive; the result is empty and both durations are zero. The tool never returns the union of the two ranges, only their common part. Every value is a full ISO 8601 timestamp, and the result is given in UTC. A range whose end comes before its start, a missing value or an invalid timestamp is rejected instead of being treated as an empty overlap, so mistakes show up straight away.
Inputs, outputs, and edge cases
Adjacent intervals that only touch at a point produce an empty result because the comparison is strict less-than, which matches scheduling systems that treat end as exclusive. Overlapping windows return the shared slice only, never a union. Wrong types, missing fields, and inverted ranges fail early so clients never see silent null overlaps.
What you can do with it
Meeting overlap
Find the shared window between two booking ranges with stable durations.
Support dashboards
Highlight when two incident windows coincide without spreadsheet math.
Automation
Call the same pure function from scripts that merge calendar feeds.
FAQ
Is this free?
Yes. Tier A runs entirely in your browser without an account.
How is the overlap of two time ranges calculated?
The overlap starts at the later of the two starts and ends at the earlier of the two ends. If that start comes before that end, the ranges share time; otherwise the result is empty with a duration of zero.
What happens when one range ends exactly when the other begins?
The result is empty. Each range's end is treated as exclusive, as most scheduling systems do, so two ranges that only touch at one instant share no time.
Does it return the combined span of both ranges?
No. It returns only the time both ranges have in common, never their union. When they do not overlap at all, you get an empty result with a duration of zero.
What happens if a range ends before it starts?
It is rejected. Missing values, invalid timestamps and inverted ranges stop the calculation with a clear message, so a typo never turns into a silent empty overlap.
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/date/interval-intersection \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"a_start":"2020-01-01T10:00:00.000Z","a_end":"2020-01-01T12:00:00.000Z","b_start":"2020-01-01T11:00:00.000Z","b_end":"2020-01-01T13:00:00.000Z"}'const res = await fetch("https://api.kit.forhosting.com/date/interval-intersection", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"a_start": "2020-01-01T10:00:00.000Z",
"a_end": "2020-01-01T12:00:00.000Z",
"b_start": "2020-01-01T11:00:00.000Z",
"b_end": "2020-01-01T13:00:00.000Z"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/date/interval-intersection",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"a_start": "2020-01-01T10:00:00.000Z",
"a_end": "2020-01-01T12:00:00.000Z",
"b_start": "2020-01-01T11:00:00.000Z",
"b_end": "2020-01-01T13:00:00.000Z"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/date/interval-intersection", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"a_start":"2020-01-01T10:00:00.000Z","a_end":"2020-01-01T12:00:00.000Z","b_start":"2020-01-01T11:00:00.000Z","b_end":"2020-01-01T13:00:00.000Z"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"a_start":"2020-01-01T10:00:00.000Z","a_end":"2020-01-01T12:00:00.000Z","b_start":"2020-01-01T11:00:00.000Z","b_end":"2020-01-01T13:00:00.000Z"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/date/interval-intersection", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"a_start": "2020-01-01T10:00:00.000Z",
"a_end": "2020-01-01T12:00:00.000Z",
"b_start": "2020-01-01T11:00:00.000Z",
"b_end": "2020-01-01T13:00:00.000Z"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "date.interval_intersection",
"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.
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
How interval intersection works
The intersection start is the maximum of the two starts and the intersection end is the minimum of the two ends. Two half-open style civil intervals A and B are defined by four ISO-8601 timestamps: a_start, a_end, b_start, and b_end. When start is strictly less than end the result is non-empty and carries start and end as UTC ISO strings plus duration_ms and duration_hours rounded to a stable decimal; otherwise empty is true, start and end are null, and both duration fields are zero.
Inputs, outputs, and edge cases
All four fields are required strings so the schema probe can build a complete sample from the published examples.
Determinism, limits, and integration
The implementation is pure parse-tier logic with no network, clocks, or randomness beyond the timestamps you supply, so identical inputs always produce identical outputs. Extremely distant timestamps remain subject to IEEE millisecond precision of the platform Date type; document that contract when you store results. Review the published schema before wiring metrics and bind only the documented success keys empty, start, end, duration_ms, and duration_hours.
Technical questions
Does it call the network?
No. The parse engine keeps everything on-device.
What if my input is invalid?
You receive invalid_input with a clear English message.
Are results stable?
Yes. Deterministic math and golden examples freeze the contract.
Who authors this capacity?
Aspire on the ForHosting KIT workshop.