Date difference API: age, duration and ISO week maths
Give two moments — birthdays, deploy times, invoice dates, or one date and now — and get back how far apart they are as years/months/days/hours/minutes/seconds, total seconds, an ISO 8601 duration, a calendar age with decimal years, each date's ISO week, and whether the span crosses a daylight-saving change.
/v1/date/diff?from=1990-05-15&to=2026-11-06&tz=Europe/London returns JSON. No key, CORS on, 60 requests a minute./v1/date/diff
Age, duration and ISO week maths between two dates. Change the values and press Send request to call the live API.
Parameters
| Name | Type | What it does | Default |
|---|---|---|---|
from required | string | Start: YYYY-MM-DD, ISO 8601 datetime, Unix timestamp or 'now' | — |
to | string | End moment (defaults to now) | now |
tz | string | IANA zone for naive inputs and DST detection | UTC |
units | string | Optional comma list to filter breakdown: years,months,days,hours,minutes,seconds | — |
Example
Request:
GET https://api.oddlathe.com/v1/date/diff?from=1990-05-15&to=2026-11-06&tz=Europe/London
Response (generated by the real code when these docs were last built; random or time-based values will differ for you):
{
"timezone": "Europe/London",
"from": {
"iso": "1990-05-15T00:00:00+01:00",
"date": "1990-05-15",
"time": "00:00:00",
"weekday": "Tuesday",
"utc_offset": "+01:00",
"abbreviation": "BST",
"dst": true,
"unix": 642726000,
"iso_week": 20,
"day_of_year": 135,
"iso_week_year": 1990,
"iso_weekday": 2
},
"to": {
"iso": "2026-11-06T00:00:00+00:00",
"date": "2026-11-06",
"time": "00:00:00",
"weekday": "Friday",
"utc_offset": "+00:00",
"abbreviation": "GMT",
"dst": false,
"unix": 1793923200,
"iso_week": 45,
"day_of_year": 310,
"iso_week_year": 2026,
"iso_weekday": 5
},
"direction": "forward",
"sign": 1,
"total_seconds": 1151197200,
"duration_iso": "P36Y5M22DT1H",
"breakdown": {
"years": 36,
…
Code examples
curl 'https://api.oddlathe.com/v1/date/diff?from=1990-05-15&to=2026-11-06&tz=Europe/London'const params = new URLSearchParams({
from: "1990-05-15",
to: "2026-11-06",
tz: "Europe/London"
});
const res = await fetch(`https://api.oddlathe.com/v1/date/diff?${params}`);
if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();
console.log(data);import json, urllib.parse, urllib.request
params = urllib.parse.urlencode({"from": "1990-05-15", "to": "2026-11-06", "tz": "Europe/London"})
url = "https://api.oddlathe.com/v1/date/diff?" + params
# Send a User-Agent: the edge network refuses Python's default one.
req = urllib.request.Request(url, headers={"User-Agent": "my-script/1.0"})
with urllib.request.urlopen(req, timeout=10) as r:
data = json.load(r)
print(data)When it's useful
- Age calculators and "how old is this account" badges
- Showing "3 years, 2 months ago" next to a timestamp from a script
- Checking whether a maintenance window crosses a DST change
- ISO week numbers for reporting periods without pulling in a date library
Good to know
fromis required;todefaults tonow. Both acceptYYYY-MM-DD, ISO 8601 datetimes, Unix seconds/milliseconds, ornow.- Naive datetimes are read as wall-clock time in
tz(default UTC). The response always includes the resolved offset and abbreviation for each end. breakdownis signed: negative components meanfromis afterto.duration_isouses the same sign as a leading-(ISO 8601).ageis the absolute calendar Y/M/D plusdecimal_yearsfrom exact elapsed seconds (Gregorian average year). Handy for birthdays; for pure elapsed time preferbreakdown/total_seconds.- Across a spring-forward, midnight-to-midnight is 23 hours of real time (and 25 hours across a fall-back).
crosses_dstis true when the UTC offset changes anywhere between the two moments. - Optional
units=years,months,days(or hours/minutes/seconds) filters which keys appear inbreakdown. Spans larger than 400 years are rejected. - Browser UI: Tooltern date difference calculator (same maths, nothing leaves your device). Also handy: the Unix time converter and time zone meeting planner.
Difference between two moments: signed Y/M/D/H/M/S breakdown, total seconds, ISO 8601 duration, calendar age (decimal years + Y/M/D), ISO week numbers, weekdays, and whether the span crosses a daylight-saving change when a time zone is given. Accepts dates, datetimes, Unix timestamps or 'now'. Pure parsing; nothing is stored.
Errors
Errors are JSON like {"error": {"code": "…", "message": "…"}}. The ones this endpoint can return:
missing_param(400): a required parameter is missing or emptybad_param(400): a value is the wrong type or out of range (the message says which)bad_timezone(400): the zone isn't a known IANA namerate_limited(429): over 60 requests a minute; wait for Retry-After seconds
Questions
How is age different from breakdown?
Age is the calendar birthday-style Y/M/D between the two dates (absolute). Breakdown also folds in the time of day and is signed. Decimal years always use exact elapsed seconds.
Does it handle leap days?
Yes. 29 February to the next 28/29 February lands on whole years; the calendar rules match civil dates.
What does crosses_dst mean?
In the given time zone, the UTC offset changes at least once between the two moments (spring-forward or fall-back). A naive hour count can then disagree with wall-clock maths.
Can I pass only one date?
Yes: omit to (or set to=now) to measure from a past or future moment to now.
Is anything stored?
Never. Pure parsing of the query string.
Related endpoints
/v1/timeCurrent time (or any moment) in a time zone, with next DST change/v1/time/convertConvert a local time between time zones/v1/workdaysCount working days between two dates, or add working days to a date/v1/cron/explainExplain a cron schedule in plain English, with next runs/v1/unitsConvert length, mass, temperature, data-size or data-rate units
Prefer a page to an API?
- Date difference calculator (age, duration, ISO weeks) on Tooltern: same job, nothing leaves your browser.
- Guide: Unix timestamp: seconds or milliseconds?
Published · OpenAPI 3.1 spec · Limits and privacy