Skip to main content

Timezone Database API

REAL DATA

Live IANA offsets, DST transitions, local-time ambiguity resolution and exact instant conversion — no guessed wall-clock mappings.

Authoritative reference data or standards computation

Base URL
/api/timezones
Capabilities
5 routes
Last updated
July 29, 2026
Data source

GET /api/timezones

Returns every zone the runtime's IANA database knows (plus UTC). Both filters are live: offsetMinutes matches the current DST-aware offset.

Live requestRuns against the public API
No key required
GET/api/timezones?country=US

Request parameters

Only zones used by this country — ISO 3166-1 alpha-2, case-insensitive (dk = DK). Mapping follows IANA zone.tab; a code with no mapped zones returns an empty list plus a warning.

Only zones whose current UTC offset is exactly this many minutes (120 ⇒ +02:00, 345 ⇒ +05:45, -210 ⇒ -03:30). DST-aware: the matching set changes with the seasons.

Advanced response options6 options

Limit the number of returned records (1–100). Defaults to all matches.

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Response format: json envelope, ndjson (one record per line) or csv.

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/timezones?country=US"
const res = await fetch("https://randomapi.dev/api/timezones?country=US");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/timezones?country=US").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/timezones?country=US"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 2
country string

Only zones used by this country — ISO 3166-1 alpha-2, case-insensitive (dk = DK). Mapping follows IANA zone.tab; a code with no mapped zones returns an empty list plus a warning.

example: country=US
offsetMinutes int

Only zones whose current UTC offset is exactly this many minutes (120 ⇒ +02:00, 345 ⇒ +05:45, -210 ⇒ -03:30). DST-aware: the matching set changes with the seasons.

allowed: -720 – 840
example: offsetMinutes=120
Universal parameters Shared response and formatting options 6
count int

Limit the number of returned records (1–100). Defaults to all matches.

default: all matches
allowed: 1 – 100
example: count=3
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=id,offset
exclude list

Return all fields except these (comma-separated).

example: exclude=isDst
format enum

Response format: json envelope, ndjson (one record per line) or csv.

default: json
allowed: json | ndjson | csv
example: format=csv
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 6
id string

IANA timezone id, exactly as the runtime's tz database reports it (e.g. Europe/Copenhagen).

example: Europe/Copenhagen

offset string (±HH:MM)

Current UTC offset, DST-aware — e.g. +01:00 for Copenhagen in winter, +02:00 in summer.

example: +02:00

offsetMinutes integer

Current UTC offset in minutes (+05:45 ⇒ 345; negative west of Greenwich, e.g. -03:30 ⇒ -210).

example: 120

countryCodes string[]

ISO 3166-1 alpha-2 codes of the countries using this zone, per IANA zone.tab. Empty for country-less zones like UTC.

example: ["DK"]

localTime string (HH:MM:SS)

Current wall-clock time in the zone, 24-hour HH:MM:SS.

example: 14:30:07

isDst boolean

Whether daylight saving time is in effect in the zone right now.

example: true

Documented examples

Build-generated requests and complete responses
3
Every timezone of the United States
GET /api/timezones?country=US
{
  "data": [
    {
      "id": "America/Adak",
      "offset": "-09:00",
      "offsetMinutes": -540,
      "countryCodes": [
        "US"
      ],
      "localTime": "23:13:22",
      "isDst": true
    },
    {
      "id": "America/Anchorage",
      "offset": "-08:00",
      "offsetMinutes": -480,
      "countryCodes": [
        "US"
      ],
      "localTime": "00:13:22",
      "isDst": true
    },
    {
      "id": "America/Boise",
      "offset": "-06:00",
      "offsetMinutes": -360,
      "countryCodes": [
        "US"
      ],
      "localTime": "02:13:22",
      "isDst": true
    },
    {
      "id": "America/Chicago",
      "offset": "-05:00",
      "offsetMinutes": -300,
      "countryCodes": [
        "US"
      ],
      "localTime": "03:13:22",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Who is at UTC+05:45 right now?
GET /api/timezones?offsetMinutes=345
{
  "data": [
    {
      "id": "Asia/Katmandu",
      "offset": "+05:45",
      "offsetMinutes": 345,
      "countryCodes": [
        "NP"
      ],
      "localTime": "13:58:22",
      "isDst": false
    }
  ],
  "meta": {
    "endpoint": "timezones",
    "count": 1,
    "params": {
      "offsetMinutes": 345
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Danish zones (case-insensitive) as CSV
GET /api/timezones?country=dk&format=csv
id,offset,offsetMinutes,countryCodes,localTime,isDst
Europe/Copenhagen,+02:00,120,"[""DK""]",10:13:22,true

GET /api/timezones/lookup

Case-insensitive id match against the runtime's IANA database. Unknown ids are an explicit 404 — browse valid ids at /api/timezones.

Live requestRuns against the public API
No key required
GET/api/timezones/lookup?id=Europe%2FCopenhagen

Request parameters

IANA timezone id, case-insensitive — e.g. Europe/Copenhagen, america/new_york or UTC. The list route enumerates every accepted id.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/timezones/lookup?id=Europe/Copenhagen"
const res = await fetch("https://randomapi.dev/api/timezones/lookup?id=Europe/Copenhagen");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/timezones/lookup?id=Europe/Copenhagen").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/timezones/lookup?id=Europe/Copenhagen"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 1
id string required

IANA timezone id, case-insensitive — e.g. Europe/Copenhagen, america/new_york or UTC. The list route enumerates every accepted id.

example: id=Europe/Copenhagen
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=id,offset
exclude list

Return all fields except these (comma-separated).

example: exclude=isDst
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 8
id string

IANA timezone id, exactly as the runtime's tz database reports it (e.g. Europe/Copenhagen).

example: Europe/Copenhagen

offset string (±HH:MM)

Current UTC offset, DST-aware — e.g. +01:00 for Copenhagen in winter, +02:00 in summer.

example: +02:00

offsetMinutes integer

Current UTC offset in minutes (+05:45 ⇒ 345; negative west of Greenwich, e.g. -03:30 ⇒ -210).

example: 120

countryCodes string[]

ISO 3166-1 alpha-2 codes of the countries using this zone, per IANA zone.tab. Empty for country-less zones like UTC.

example: ["DK"]

localDate string (YYYY-MM-DD)

Current calendar date on the zone's local wall clock (can differ from the UTC date).

example: 2026-06-11

localTime string (HH:MM:SS)

Current wall-clock time in the zone, 24-hour HH:MM:SS.

example: 14:30:07

weekday string

English weekday name of the zone's current local date.

example: Thursday

isDst boolean

Whether daylight saving time is in effect in the zone right now.

example: true

Documented examples

Build-generated requests and complete responses
3
Copenhagen right now
GET /api/timezones/lookup?id=Europe/Copenhagen
{
  "data": {
    "id": "Europe/Copenhagen",
    "offset": "+02:00",
    "offsetMinutes": 120,
    "countryCodes": [
      "DK"
    ],
    "localDate": "2026-07-29",
    "localTime": "10:13:22",
    "weekday": "Wednesday",
    "isDst": true
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/lookup",
    "params": {
      "id": "Europe/Copenhagen"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Case-insensitive lookup
GET /api/timezones/lookup?id=america/new_york
{
  "data": {
    "id": "America/New_York",
    "offset": "-04:00",
    "offsetMinutes": -240,
    "countryCodes": [
      "US"
    ],
    "localDate": "2026-07-29",
    "localTime": "04:13:22",
    "weekday": "Wednesday",
    "isDst": true
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/lookup",
    "params": {
      "id": "America/New_York"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
UTC reference clock
GET /api/timezones/lookup?id=UTC&fields=localDate,localTime
{
  "data": {
    "localDate": "2026-07-29",
    "localTime": "08:13:22"
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/lookup",
    "params": {
      "id": "UTC"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

GET /api/timezones/convert

Accepts only the shared absolute date profile: date-only UTC midnight or RFC3339 with Z/explicit offset. It never parses a naive local wall time.

Live requestRuns against the public API
No key required
GET/api/timezones/convert?at=2026-01-15T12%3A00%3A00Z&zone=america%2Fnew_york

Request parameters

Absolute instant: YYYY-MM-DD (UTC midnight) or RFC3339 with Z/explicit offset, seconds and at most millisecond precision. Naive local timestamps are invalid.

IANA timezone id, case-insensitive. Canonical casing follows the runtime inventory returned by /api/timezones; UTC is always accepted.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/timezones/convert?at=2026-01-15T12:00:00Z&zone=america/new_york"
const res = await fetch("https://randomapi.dev/api/timezones/convert?at=2026-01-15T12:00:00Z&zone=america/new_york");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/timezones/convert?at=2026-01-15T12:00:00Z&zone=america/new_york").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/timezones/convert?at=2026-01-15T12:00:00Z&zone=america/new_york"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 2
at date required

Absolute instant: YYYY-MM-DD (UTC midnight) or RFC3339 with Z/explicit offset, seconds and at most millisecond precision. Naive local timestamps are invalid.

example: at=2026-01-15T12:00:00.125Z
zone string required

IANA timezone id, case-insensitive. Canonical casing follows the runtime inventory returned by /api/timezones; UTC is always accepted.

example: zone=America/New_York
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=instant,epochMilliseconds
exclude list

Return all fields except these (comma-separated).

example: exclude=isDst
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 9
instant string (ISO 8601 UTC)

Canonical UTC rendering of the absolute input, preserving milliseconds.

example: 2026-01-15T12:00:00.125Z

epochMilliseconds integer

The same instant as exact signed milliseconds since the Unix epoch.

example: 1768478400125

zone string

Canonical runtime IANA timezone id.

example: America/New_York

localDate string (ISO 8601 date)

Calendar date at the instant in zone; extended ISO years are preserved at parser boundaries.

example: 2026-01-15

localTime string (HH:MM:SS.SSS)

Wall-clock time at the instant in zone, preserving milliseconds.

example: 07:00:00.125

weekday string

English weekday of the local calendar date.

example: Thursday

offset string (±HH:MM[:SS])

UTC offset at the instant; historical second precision is retained when present.

example: -05:00

offsetMinutes number

The same offset in minutes; fractional only for historical second-based offsets.

example: -300

isDst boolean

Whether daylight saving time is in effect in zone at this exact instant.

example: false

Documented examples

Build-generated requests and complete responses
3
New York winter instant
GET /api/timezones/convert?at=2026-01-15T12:00:00Z&zone=america/new_york
{
  "data": {
    "instant": "2026-01-15T12:00:00.000Z",
    "epochMilliseconds": 1768478400000,
    "zone": "America/New_York",
    "localDate": "2026-01-15",
    "localTime": "07:00:00.000",
    "weekday": "Thursday",
    "offset": "-05:00",
    "offsetMinutes": -300,
    "isDst": false
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/convert",
    "params": {
      "at": "2026-01-15T12:00:00.000Z",
      "zone": "America/New_York"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Chatham quarter-hour and milliseconds
GET /api/timezones/convert?at=2026-01-15T12:00:00.125Z&zone=Pacific/Chatham
{
  "data": {
    "instant": "2026-01-15T12:00:00.125Z",
    "epochMilliseconds": 1768478400125,
    "zone": "Pacific/Chatham",
    "localDate": "2026-01-16",
    "localTime": "01:45:00.125",
    "weekday": "Friday",
    "offset": "+13:45",
    "offsetMinutes": 825,
    "isDst": true
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/convert",
    "params": {
      "at": "2026-01-15T12:00:00.125Z",
      "zone": "Pacific/Chatham"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Date-only UTC midnight
GET /api/timezones/convert?at=2026-07-15&zone=UTC
{
  "data": {
    "instant": "2026-07-15T00:00:00.000Z",
    "epochMilliseconds": 1784073600000,
    "zone": "UTC",
    "localDate": "2026-07-15",
    "localTime": "00:00:00.000",
    "weekday": "Wednesday",
    "offset": "+00:00",
    "offsetMinutes": 0,
    "isDst": false
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/convert",
    "params": {
      "at": "2026-07-15",
      "zone": "UTC"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

GET /api/timezones/transitions

Scans an explicit UTC range of at most 370 elapsed days and binary-resolves each detected offset change to the first changed millisecond exposed by Intl.

Live requestRuns against the public API
No key required
GET/api/timezones/transitions?zone=Europe%2FCopenhagen&from=2026-01-01&to=2027-01-01

Request parameters

IANA timezone id, case-insensitive; canonical casing is echoed in meta.params.

Inclusive absolute range start in years 1900–2100: date-only UTC midnight or RFC3339 with Z/offset.

Exclusive absolute range end, strictly after from and no more than 370 elapsed days later.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/timezones/transitions?zone=Europe/Copenhagen&from=2026-01-01&to=2027-01-01"
const res = await fetch("https://randomapi.dev/api/timezones/transitions?zone=Europe/Copenhagen&from=2026-01-01&to=2027-01-01");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/timezones/transitions?zone=Europe/Copenhagen&from=2026-01-01&to=2027-01-01").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/timezones/transitions?zone=Europe/Copenhagen&from=2026-01-01&to=2027-01-01"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 3
zone string required

IANA timezone id, case-insensitive; canonical casing is echoed in meta.params.

example: zone=Europe/Copenhagen
from date required

Inclusive absolute range start in years 1900–2100: date-only UTC midnight or RFC3339 with Z/offset.

example: from=2026-01-01
to date required

Exclusive absolute range end, strictly after from and no more than 370 elapsed days later.

example: to=2027-01-01
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=zone,from
exclude list

Return all fields except these (comma-separated).

example: exclude=transitions
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 5
zone string

Canonical runtime IANA timezone id.

example: Europe/Copenhagen

from string (ISO 8601 UTC)

Inclusive canonical UTC range start.

example: 2026-01-01T00:00:00.000Z

to string (ISO 8601 UTC)

Exclusive canonical UTC range end.

example: 2027-01-01T00:00:00.000Z

count integer

Number of offset transitions found in the bounded range.

example: 2

transitions object[]

Chronological transitions with instant, gap/fold kind, offsets before/after, deltaSeconds and exact adjacent local wall-clock values.

example: [{"instant":"2026-03-29T01:00:00.000Z","kind":"gap","offsetBefore":"+01:00","offsetAfter":"+02:00","offsetBeforeMinutes":60,"offsetAfterMinutes":120,"deltaSeconds":3600,"localBefore":"2026-03-29T01:59:59.999","localAfter":"2026-03-29T03:00:00.000"}]

Documented examples

Build-generated requests and complete responses
3
Copenhagen's 2026 DST changes
GET /api/timezones/transitions?zone=Europe/Copenhagen&from=2026-01-01&to=2027-01-01
{
  "data": {
    "zone": "Europe/Copenhagen",
    "from": "2026-01-01T00:00:00.000Z",
    "to": "2027-01-01T00:00:00.000Z",
    "count": 2,
    "transitions": [
      {
        "instant": "2026-03-29T01:00:00.000Z",
        "kind": "gap",
        "offsetBefore": "+01:00",
        "offsetAfter": "+02:00",
        "offsetBeforeMinutes": 60,
        "offsetAfterMinutes": 120,
        "deltaSeconds": 3600,
        "localBefore": "2026-03-29T01:59:59.999",
        "localAfter": "2026-03-29T03:00:00.000"
      },
      {
        "instant": "2026-10-25T01:00:00.000Z",
        "kind": "fold",
        "offsetBefore": "+02:00",
        "offsetAfter": "+01:00",
        "offsetBeforeMinutes": 120,
        "offsetAfterMinutes": 60,
        "deltaSeconds": -3600,
        "localBefore": "2026-10-25T02:59:59.999",
        "localAfter": "2026-10-25T02:00:00.000"
      }
    ]
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/transitions",
    "params": {
      "zone": "Europe/Copenhagen",
      "from": "2026-01-01",
      "to": "2027-01-01"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Lord Howe's half-hour transitions
GET /api/timezones/transitions?zone=Australia/Lord_Howe&from=2026-01-01&to=2027-01-01
{
  "data": {
    "zone": "Australia/Lord_Howe",
    "from": "2026-01-01T00:00:00.000Z",
    "to": "2027-01-01T00:00:00.000Z",
    "count": 2,
    "transitions": [
      {
        "instant": "2026-04-04T15:00:00.000Z",
        "kind": "fold",
        "offsetBefore": "+11:00",
        "offsetAfter": "+10:30",
        "offsetBeforeMinutes": 660,
        "offsetAfterMinutes": 630,
        "deltaSeconds": -1800,
        "localBefore": "2026-04-05T01:59:59.999",
        "localAfter": "2026-04-05T01:30:00.000"
      },
      {
        "instant": "2026-10-03T15:30:00.000Z",
        "kind": "gap",
        "offsetBefore": "+10:30",
        "offsetAfter": "+11:00",
        "offsetBeforeMinutes": 630,
        "offsetAfterMinutes": 660,
        "deltaSeconds": 1800,
        "localBefore": "2026-10-04T01:59:59.999",
        "localAfter": "2026-10-04T02:30:00.000"
      }
    ]
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/transitions",
    "params": {
      "zone": "Australia/Lord_Howe",
      "from": "2026-01-01",
      "to": "2027-01-01"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
UTC has no offset transitions
GET /api/timezones/transitions?zone=UTC&from=2026-01-01&to=2027-01-01
{
  "data": {
    "zone": "UTC",
    "from": "2026-01-01T00:00:00.000Z",
    "to": "2027-01-01T00:00:00.000Z",
    "count": 0,
    "transitions": []
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/transitions",
    "params": {
      "zone": "UTC",
      "from": "2026-01-01",
      "to": "2027-01-01"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

GET /api/timezones/resolve-local

Returns every real instant matching the supplied local time. Unique values have one candidate, folds two, and gaps zero plus the missing interval; only actual fold candidates may be selected.

Live requestRuns against the public API
No key required
GET/api/timezones/resolve-local?zone=Europe%2FCopenhagen&local=2026-10-25T02%3A30%3A00&disambiguation=earlier

Request parameters

IANA timezone id, case-insensitive; canonical casing is echoed in meta.params.

Naive local wall-clock timestamp YYYY-MM-DDTHH:mm:ss[.SSS], without Z/offset, in years 1900–2100.

reject leaves a repeated time unselected; earlier/later selects one of its actual candidates. A nonexistent gap is never shifted or invented under any option.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/timezones/resolve-local?zone=Europe/Copenhagen&local=2026-10-25T02:30:00&disambiguation=earlier"
const res = await fetch("https://randomapi.dev/api/timezones/resolve-local?zone=Europe/Copenhagen&local=2026-10-25T02:30:00&disambiguation=earlier");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/timezones/resolve-local?zone=Europe/Copenhagen&local=2026-10-25T02:30:00&disambiguation=earlier").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/timezones/resolve-local?zone=Europe/Copenhagen&local=2026-10-25T02:30:00&disambiguation=earlier"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 3
zone string required

IANA timezone id, case-insensitive; canonical casing is echoed in meta.params.

example: zone=Europe/Copenhagen
local string required

Naive local wall-clock timestamp YYYY-MM-DDTHH:mm:ss[.SSS], without Z/offset, in years 1900–2100.

allowed: 19 – 23
example: local=2026-10-25T02:30:00
disambiguation enum

reject leaves a repeated time unselected; earlier/later selects one of its actual candidates. A nonexistent gap is never shifted or invented under any option.

default: reject
allowed: reject | earlier | later
example: disambiguation=earlier
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=zone,local
exclude list

Return all fields except these (comma-separated).

example: exclude=gap
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 7
zone string

Canonical runtime IANA timezone id.

example: Europe/Copenhagen

local string

Canonical millisecond-precision naive wall-clock timestamp.

example: 2026-10-25T02:30:00.000

status string

unique, ambiguous or nonexistent.

example: ambiguous

candidates object[]

Every real matching instant, ordered earlier first, with its exact offset; length is 1, 2 or 0 by status.

example: [{"instant":"2026-10-25T00:30:00.000Z","offset":"+02:00","offsetMinutes":120},{"instant":"2026-10-25T01:30:00.000Z","offset":"+01:00","offsetMinutes":60}]

selectedInstant string (ISO 8601 UTC) nullable

Unique/explicitly selected actual instant, or null for rejected ambiguity/nonexistence.

example: 2026-10-25T00:30:00.000Z

selectedOffset string nullable

UTC offset of selectedInstant, or null when nothing was selected.

example: +02:00

gap object nullable

For nonexistent local times only: transition instant, inclusive missing-local start, exclusive end and durationSeconds; otherwise null.

example: {"transitionInstant":"2026-03-29T01:00:00.000Z","localStart":"2026-03-29T02:00:00.000","localEnd":"2026-03-29T03:00:00.000","durationSeconds":3600}

Documented examples

Build-generated requests and complete responses
3
Select the earlier Copenhagen fold instant
GET /api/timezones/resolve-local?zone=Europe/Copenhagen&local=2026-10-25T02:30:00&disambiguation=earlier
{
  "data": {
    "zone": "Europe/Copenhagen",
    "local": "2026-10-25T02:30:00.000",
    "status": "ambiguous",
    "candidates": [
      {
        "instant": "2026-10-25T00:30:00.000Z",
        "offset": "+02:00",
        "offsetMinutes": 120
      },
      {
        "instant": "2026-10-25T01:30:00.000Z",
        "offset": "+01:00",
        "offsetMinutes": 60
      }
    ],
    "selectedInstant": "2026-10-25T00:30:00.000Z",
    "selectedOffset": "+02:00",
    "gap": null
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/resolve-local",
    "params": {
      "zone": "Europe/Copenhagen",
      "local": "2026-10-25T02:30:00.000",
      "disambiguation": "earlier"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Expose a nonexistent spring-forward time
GET /api/timezones/resolve-local?zone=Europe/Copenhagen&local=2026-03-29T02:30:00
{
  "data": {
    "zone": "Europe/Copenhagen",
    "local": "2026-03-29T02:30:00.000",
    "status": "nonexistent",
    "candidates": [],
    "selectedInstant": null,
    "selectedOffset": null,
    "gap": {
      "transitionInstant": "2026-03-29T01:00:00.000Z",
      "localStart": "2026-03-29T02:00:00.000",
      "localEnd": "2026-03-29T03:00:00.000",
      "durationSeconds": 3600
    }
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/resolve-local",
    "params": {
      "zone": "Europe/Copenhagen",
      "local": "2026-03-29T02:30:00.000",
      "disambiguation": "reject"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Resolve an ordinary Tokyo wall clock
GET /api/timezones/resolve-local?zone=Asia/Tokyo&local=2026-07-15T21:00:00
{
  "data": {
    "zone": "Asia/Tokyo",
    "local": "2026-07-15T21:00:00.000",
    "status": "unique",
    "candidates": [
      {
        "instant": "2026-07-15T12:00:00.000Z",
        "offset": "+09:00",
        "offsetMinutes": 540
      }
    ],
    "selectedInstant": "2026-07-15T12:00:00.000Z",
    "selectedOffset": "+09:00",
    "gap": null
  },
  "meta": {
    "endpoint": "timezones",
    "route": "/resolve-local",
    "params": {
      "zone": "Asia/Tokyo",
      "local": "2026-07-15T21:00:00.000",
      "disambiguation": "reject"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

About this API

Coverage & behavior

Real timezone data straight from the runtime's IANA tz database (via Intl), so newly released tzdb rules apply automatically — nothing here is hardcoded or stale. List and lookup values are computed live at request time; conversion values are computed for the exact supplied instant. This endpoint takes no seed.

  • /api/timezones — every zone with its current offset, local time, DST status and countries. ?country= keeps only the zones a country uses (ISO 3166-1 alpha-2, case-insensitive, mapping derived from IANA zone.tab), and ?offsetMinutes= keeps only zones currently at exactly that offset — DST-aware, so the matching set shifts with the seasons.
  • /api/timezones/lookup — one zone by id, case-insensitive (europe/copenhagen works), with local date, time and weekday. Unknown ids are an explicit 404 pointing back to the list — never a guessed substitute.
  • /api/timezones/convert — one absolute at instant rendered in a case-insensitive IANA zone, with canonical UTC, exact epoch milliseconds, local date/time/weekday, offset and DST at that instant. Date-only input means UTC midnight; timestamps must carry Z or an explicit offset. Naive local timestamps are rejected, so the route neither parses ambiguous wall time nor makes a false daylight-saving ambiguity claim.
  • /api/timezones/transitions — every offset change in an explicit UTC range of at most 370 days, binary-resolved to the first changed millisecond exposed by Intl. Each row identifies a forward gap or backward fold, offsets before/after and the local clock jump.
  • /api/timezones/resolve-local — maps a strict naive wall-clock value to zero, one or two real instants. A fold returns both candidates; a gap returns none plus its exact missing local interval. disambiguation=earlier|later may select an actual fold candidate, while the default reject never chooses silently. Nonexistent times are never shifted into existence.

Zone ids are whatever the runtime's tz database considers canonical; some runtimes report legacy spellings (e.g. Asia/Calcutta for Asia/Kolkata) — the country mapping covers both. The list exposes that canonical inventory, while lookup, conversion, transitions and local resolution also accept case-insensitive IANA links/aliases recognized by the runtime and echo the resolved canonical id. UTC is always included and maps to no country (countryCodes: []). Historical offsets with second precision are preserved on /convert; their offsetMinutes value can therefore be fractional.

Use it for

  • Build a timezone picker grouped by country with live UTC offsets
  • Show 'current time in …' for any city zone without shipping a tz library
  • Render one stored UTC timestamp in a user's canonical IANA zone
  • Find every zone currently at a given offset to plan meeting or maintenance windows
  • Audit DST gaps/folds and resolve user-entered local times without silently guessing

Frequently asked questions

Are DST transitions handled?

Yes. List and lookup use the request-time instant; /convert uses the supplied at instant. Europe/London therefore answers +00:00 or +01:00 for the date actually evaluated.

Can I list a country's timezones?

country=US returns all matching zones with their current local times — filters return every match, never a sample.

How do I look up a single zone?

/api/timezones/lookup?id=Asia/Tokyo — and unknown ids answer 404 honestly.

Can I convert a local wall-clock time to UTC?

Use /resolve-local: it returns zero candidates for a DST gap, two for a repeated fold and one for an ordinary time. /convert remains the route for already-absolute instants.

Can I list a zone's daylight-saving transitions?

Yes. /transitions returns every offset change in an explicit UTC range up to 370 days, including before/after offsets and the local gap or fold.