Midpoint between two dates
Finding the midpoint between two dates answers a different question from counting whole days, building a countdown, or computing age: it asks for the single instant that sits exactly halfway between two known points on the timeline.
Run — free
This midpoint-between-two-dates calculator accepts two explicit ISO-8601 datetimes—full timestamps with Z or numeric offsets, or date-only strings treated as midnight UTC—converts both to epoch milliseconds with pure Gregorian arithmetic, averages those instants with a deterministic floor of the sum, and returns the halfway datetime formatted as UTC with millisecond precision. Classic checks include midnight-to-midnight on consecutive days landing at noon, a one-second span landing at the half-second, and identical endpoints returning the same instant. The engine never consults the host clock, never calls the network, and never uses the platform Date object, so the same inputs always produce the same midpoint in the free browser widget and in the API path priced at $0.002 per successful request. Use it for project halfway markers, experiment midpoints, billing window centers, and reproducible fixtures in CI.
What an instant midpoint means and what the response contains
Averaging two absolute instants is the timeline analogue of finding the midpoint of a segment on a number line: if you know the start and end times of a meeting, a study, a campaign, or a contract window, the midpoint is the unique UTC instant that is equidistant in milliseconds from both ends. That is not the same as the calendar mid-date of a multi-day span when people casually say “halfway through March,” nor is it a business-day midpoint that skips weekends, nor a wall-clock average that pretends every civil day has exactly twenty-four hours while ignoring offsets. You supply start and end as ISO-8601 strings; each may be a full datetime with optional fractional seconds and a Z or plus-minus hour-minute offset, or a date-only YYYY-MM-DD value that is treated as midnight UTC so pure calendar pairs still work. The calculator validates that both days exist on the Gregorian calendar—including leap days only in leap years—converts each input to a UTC epoch millisecond count using proleptic civil arithmetic, then sets midpoint_epoch_ms to the floor of the sum of the two epochs divided by two so that an odd total of milliseconds still yields a single deterministic half-millisecond choice. The response echoes the original start and end strings for auditability, returns midpoint as a UTC ISO string with three fractional digits and a trailing Z, reports start_epoch_ms, end_epoch_ms, and midpoint_epoch_ms for numeric pipelines, and includes span_ms as the absolute distance plus signed_span_ms as end minus start so you can see direction when the second instant is earlier than the first. A short formula field restates the average so clients can document the contract next to the answer. Rejected cases include a missing start or end field, strings that are not ISO-8601, impossible months or days such as 2023-02-29, invalid clock components, and years outside one through 9999. If you need whole calendar day counts, remaining countdown parts, or age in years and months, use those dedicated tools; this page answers only the exact halfway instant between two validated timestamps.
How start and end are read and how the midpoint stays reproducible
The preferred first field is start, but aliases from, date1, a, and begin are accepted so spreadsheets, query strings, and typed forms can reuse the same contract without renaming columns. The preferred second field is end, with aliases to, date2, b, and finish for the same reason. Each string is trimmed; date-only values become midnight UTC; datetimes may use T or a space between date and time; fractional seconds are accepted and truncated to whole milliseconds before averaging so sub-millisecond noise does not invent a second midpoint. Offsets such as plus zero two colon zero zero or minus zero five colon zero zero are converted into UTC by subtracting the offset minutes from the local civil epoch, so a New York evening and a Paris morning that refer to the same absolute interval still average correctly in UTC. Internally the engine maps each civil triple to a serial day count with the well-known days_from_civil mapping, multiplies by eighty-six million four hundred thousand milliseconds per day, adds the time-of-day milliseconds, and adjusts for the offset—pure integer arithmetic with no Date, Math.random, or network I/O. The midpoint is then reformatted with the inverse civil_from_days mapping so the printed UTC string matches the numeric midpoint_epoch_ms exactly. Identical inputs yield the same instant as midpoint; reversing the pair leaves the midpoint and the absolute span unchanged and only flips the sign of signed_span_ms. Because every step is deterministic, the free browser run on this page and the priced API path agree byte-for-byte on the same module, which is ideal for CI fixtures that pin 2024-01-01T12:00:00.000Z as the midpoint of consecutive midnights without re-implementing leap-year tables by hand.
Where midpoint datetime arithmetic fits in planning, science, and software
Project managers mark halfway checkpoints when a launch window or sprint is defined by two explicit timestamps and stakeholders want a single mid-window review time rather than a vague mid-week label. Researchers and lab systems record the midpoint of an observation interval so summary tables show one representative instant for plots and joins without choosing the start or the end arbitrarily. Finance and operations teams center billing or notice windows when a policy refers to the middle of a period that is already stored as a pair of ISO instants in a ledger. Developers call the contract from scripts to generate deterministic midpoints for schedulers, to assert halfway fields in reports, or to satisfy product requirements that demand pure UTC averaging without timezone drift from the host Date object. Educators and standards writers use the tool to demonstrate that the midpoint of a one-second span is the half-second, and that offset-aware inputs still collapse to a single Z-normalized answer. On this page the work runs entirely in your browser; through the API each successful lookup costs $0.002, failed validation is not charged, and nothing is stored after the response returns. That split—free interactive exploration and a priced, identical API—matches the rest of the KIT tier-A catalog and lets you move from a one-off check to a pipeline without changing the mathematical result. Pair it with days-between, countdown-between, or epoch helpers when you need related timeline steps, and keep this page for the search intent of finding the midpoint between two dates as an exact datetime.
What you can do with it
Project and campaign halfway markers
Compute the exact mid-window review time for a sprint, launch, or marketing campaign defined by two ISO timestamps.
Observation and experiment midpoints
Record a single representative UTC instant for an observation interval so plots and joins do not pick start or end arbitrarily.
Deterministic CI and billing fixtures
Generate reproducible midpoint values for unit tests, ledger centers, and pipelines without depending on Date or the host clock.
FAQ
What does the midpoint between two dates calculator cost?
It is free in your browser on this page. Through the API a successful request costs $0.002; invalid inputs are not charged.
How is the midpoint defined?
Both inputs are converted to UTC epoch milliseconds. midpoint_epoch_ms is floor((start_ms + end_ms) / 2), then formatted as a UTC ISO-8601 string with millisecond precision.
Do time zones and offsets affect the result?
Yes, correctly: offsets on either input are converted to UTC before averaging. The midpoint is always returned with a trailing Z in UTC.
What if the two datetimes are the same, or end is before start?
Identical inputs return that same instant as the midpoint. If end is earlier than start, the midpoint is unchanged and only signed_span_ms becomes negative.
Are date-only values accepted?
Yes. A YYYY-MM-DD string is treated as midnight UTC for that calendar day, then averaged like any other instant.
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/midpoint-between-dates \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"start":"2024-01-01T00:00:00Z","end":"2024-01-02T00:00:00Z"}'const res = await fetch("https://api.kit.forhosting.com/date/midpoint-between-dates", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"start": "2024-01-01T00:00:00Z",
"end": "2024-01-02T00:00:00Z"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/date/midpoint-between-dates",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"start": "2024-01-01T00:00:00Z",
"end": "2024-01-02T00:00:00Z"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/date/midpoint-between-dates", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"start":"2024-01-01T00:00:00Z","end":"2024-01-02T00:00:00Z"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"start":"2024-01-01T00:00:00Z","end":"2024-01-02T00:00:00Z"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/date/midpoint-between-dates", 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": "2024-01-01T00:00:00Z",
"end": "2024-01-02T00:00:00Z"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "date.midpoint_between_dates",
"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. |