Timezone

Timezone transitions

List the UTC offset and abbreviation changes (daylight saving starts and ends) for the timezone at a point over a date range.

Signed in? Open this endpoint in the dashboard playground, which uses your organization automatically. Signed out, use Try in Playground below with your API key.

GET
/timezone/transitions

Authorization

queryapiKey<token>

Your API key from the dashboard, sent as ?apiKey=<key>.

Query Parameters

lat*number

Latitude.

Range-90 <= value <= 90
lon*number

Longitude.

Range-180 <= value <= 180
from*string

RFC 3339 start instant (exclusive). Percent-encode a + offset as %2B; an unencoded + that arrives as a space is repaired.

Deviation (approximated): exclusive, and not limited to 2025-01-01 or later.

Formatdate-time
to*string

RFC 3339 end instant (inclusive). Must not be before from; at most 50 years after it.

Deviation (approximated): inclusive, and not limited to 2032-01-01 or earlier.

Formatdate-time

Response Body

Transitions per covering timezone.

application/json
  1. response
lat*number

Echo of the query lat.

lon*number

Echo of the query lon.

from*string

Query from, normalised to UTC without fractional seconds.

Formatdate-time
to*string

Query to, normalised to UTC without fractional seconds.

Formatdate-time
tzdb_version*string

tzdb release the offsets and transitions come from.

timezones*array<>

Every zone polygon covering the point (normally one; two where polygons overlap; empty over open ocean or outside the data).

Example Request
curl -X GET 'https://api.data.graphitelab.ai/v1/timezone/transitions?lat=43.65&lon=-79.38&from=2027-01-01T00%3A00%3A00Z&to=2028-01-01T00%3A00%3A00Z'
Example Response
{  "lat": 43.65,  "lon": -79.38,  "from": "2027-01-01T00:00:00Z",  "to": "2028-01-01T00:00:00Z",  "tzdb_version": "2026f",  "timezones": [    {      "name": "America/Toronto",      "transitions": [        {          "at": "2027-03-14T07:00:00Z",          "before": {            "type": "standard",            "utc_offset": "-05:00",            "offset_seconds": -18000,            "abbreviation": "EST"          },          "after": {            "type": "daylightSaving",            "utc_offset": "-04:00",            "offset_seconds": -14400,            "abbreviation": "EDT"          },          "offset_change_seconds": 3600,          "kind": "daylight-start"        },        {          "at": "2027-11-07T06:00:00Z",          "before": {            "type": "daylightSaving",            "utc_offset": "-04:00",            "offset_seconds": -14400,            "abbreviation": "EDT"          },          "after": {            "type": "standard",            "utc_offset": "-05:00",            "offset_seconds": -18000,            "abbreviation": "EST"          },          "offset_change_seconds": -3600,          "kind": "daylight-end"        }      ]    }  ]}

Returns every offset or abbreviation change, such as a daylight saving start or end, for the timezone(s) covering a coordinate between from and to. Use it to schedule across a DST boundary or to know exactly when a zone's clocks change. For the current offset and the next change only, use the timezone endpoint. Endpoint: GET /v1/timezone/transitions.

How it works

  1. A PostGIS point-in-polygon lookup (ST_Covers) against the timezone-boundary-builder polygons (release 2026f) finds the IANA zone(s) at lat/lon.

  2. For each zone, the gateway scans the range one day at a time using the Node ICU tzdata, which is pinned to the same tzdb release. When the offset or abbreviation differs across a day, it bisects down to the exact second.

No routing or geocoding Engine is involved, and no external service is called. The response reports the tzdb release that ICU actually loaded as tzdb_version.

Quick start

curl -s "https://api.data.graphitelab.ai/v1/timezone/transitions?lat=43.65&lon=-79.38&from=2027-01-01T00:00:00Z&to=2028-01-01T00:00:00Z&apiKey=$GRAPHITE_API_KEY"
{
  "lat": 43.65,
  "lon": -79.38,
  "from": "2027-01-01T00:00:00Z",
  "to": "2028-01-01T00:00:00Z",
  "tzdb_version": "2026f",
  "timezones": [
    {
      "name": "America/Toronto",
      "transitions": [
        {
          "at": "2027-03-14T07:00:00Z",
          "before": { "type": "standard", "utc_offset": "-05:00", "offset_seconds": -18000, "abbreviation": "EST" },
          "after": { "type": "daylightSaving", "utc_offset": "-04:00", "offset_seconds": -14400, "abbreviation": "EDT" },
          "offset_change_seconds": 3600,
          "kind": "daylight-start"
        },
        {
          "at": "2027-11-07T06:00:00Z",
          "before": { "type": "daylightSaving", "utc_offset": "-04:00", "offset_seconds": -14400, "abbreviation": "EDT" },
          "after": { "type": "standard", "utc_offset": "-05:00", "offset_seconds": -18000, "abbreviation": "EST" },
          "offset_change_seconds": -3600,
          "kind": "daylight-end"
        }
      ]
    }
  ]
}

Parameters

NameTypeRequiredWhat it does
latnumber (-90 to 90)yesLatitude.
lonnumber (-180 to 180)yesLongitude.
fromstring, RFC 3339 date-timeyesStart instant, exclusive. Percent-encode a + offset as %2B; an unencoded + that arrives as a space is repaired.
tostring, RFC 3339 date-timeyesEnd instant, inclusive. Must not be before from and at most 50 years after it.

Full parameter reference

Response

FieldMeaning
lat, lonEcho of the query.
from, toQuery instants normalized to UTC without fractional seconds.
tzdb_versiontzdb release the offsets and transitions come from (for example 2026f).
timezonesOne entry per zone polygon covering the point. Normally one; empty over open ocean or outside the data.
timezones[].nameIANA zone name (the tzid). Its Place ID would be gp:tz:<tzid> (ADR 0006), but this endpoint returns only the name.
timezones[].transitionsChanges in time order; empty when the zone has none in the range.
atUTC instant of the change, to the second.
before, afterOffset state either side: type, utc_offset (+HH:MM), offset_seconds, abbreviation.
offset_change_secondsafter.offset_seconds - before.offset_seconds; 0 for a pure abbreviation change.
kinddaylight-start, daylight-end, offset-change or designation-change.

type is standard when the offset equals the smaller of the zone's January and July offsets that year, daylightSaving when larger, and other when smaller. The abbreviation may be a GMT offset such as GMT-5 where tzdb has no abbreviation.

No place_id, datasource or rank is returned by this endpoint.

Differences from Geoapify

  • approximated: the interval is (from, to]. A transition exactly at from is not listed; one exactly at to is. Geoapify uses [from, to).

  • approximated: the maximum span is 50 years, and any date is accepted. Geoapify limits the span to 366 days within 2025-01-01 to 2032-01-01.

  • extra: timezones can hold zero or several zones (overlapping polygons), and at is rendered without fractional seconds. Offsets are computed for each zone name directly.

Nothing from Geoapify's parameter list is dropped.

US and Canada notes

Zones come from the full timezone-boundary-builder release, not from a US/Canada extract, so the lookup is not limited to the two countries. Both examples on this page are in the two countries: Toronto observes DST, and Indianapolis (America/Indiana/Indianapolis) is a distinct IANA zone that has the same 2027 transitions as the Eastern zone.

More examples

Indianapolis, calendar year 2027. Shows the Indiana zone name and the same DST pair of changes.

curl -s "https://api.data.graphitelab.ai/v1/timezone/transitions?lat=39.77&lon=-86.16&from=2027-01-01T00:00:00Z&to=2028-01-01T00:00:00Z&apiKey=$GRAPHITE_API_KEY"

Errors and limits

StatusWhen
400Missing or invalid lat, lon, from or to; to before from; range over 50 years.
401Missing or invalid apiKey.
500Internal error.

Limits: from and to must be RFC 3339 date-times, and to - from must not exceed 50 x 366 days.

Try in Playground (signed in to your Graphite Lab organization). Signed out, use the paste-your-key widget on the reference page.