AnvilJSON utilities

Anvil › Docs › /v1/date/diff

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.

In one line: GET /v1/date/diff?from=1990-05-15&to=2026-11-06&tz=Europe/London returns JSON. No key, CORS on, 60 requests a minute.
GET

/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

NameTypeWhat it doesDefault
from requiredstringStart: YYYY-MM-DD, ISO 8601 datetime, Unix timestamp or 'now'—
tostringEnd moment (defaults to now)now
tzstringIANA zone for naive inputs and DST detectionUTC
unitsstringOptional 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
curl 'https://api.oddlathe.com/v1/date/diff?from=1990-05-15&to=2026-11-06&tz=Europe/London'
JavaScript (browser or Node 18+)
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);
Python (standard library only)
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

  • from is required; to defaults to now. Both accept YYYY-MM-DD, ISO 8601 datetimes, Unix seconds/milliseconds, or now.
  • Naive datetimes are read as wall-clock time in tz (default UTC). The response always includes the resolved offset and abbreviation for each end.
  • breakdown is signed: negative components mean from is after to. duration_iso uses the same sign as a leading - (ISO 8601).
  • age is the absolute calendar Y/M/D plus decimal_years from exact elapsed seconds (Gregorian average year). Handy for birthdays; for pure elapsed time prefer breakdown / total_seconds.
  • Across a spring-forward, midnight-to-midnight is 23 hours of real time (and 25 hours across a fall-back). crosses_dst is true when the UTC offset changes anywhere between the two moments.
  • Optional units=years,months,days (or hours/minutes/seconds) filters which keys appear in breakdown. 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 empty
  • bad_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 name
  • rate_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

Prefer a page to an API?

Published · OpenAPI 3.1 spec · Limits and privacy