Skip to main content

Timezone handling

All timestamps in the MyTrafficData API are ISO 8601 strings. The only thing that varies between fields is whether the string carries a UTC offset — and that small detail tells you exactly how to interpret the value.

TL;DR

Field typeFormatExample
Server metadata (created, completed, expires, last-login…)UTC, +00:00 offset2026-01-15T09:30:00+00:00
Measurement data with a known site timezoneSite-local time, site offset2026-01-15T10:30:00+01:00
Measurement data with no known timezone (rare)Bare ISO, no offset2026-01-15T10:30:00

If the timestamp has an offset, parse it as that absolute instant. If it has no offset, treat it as wall-clock time in some unknown timezone — don't convert it.


1. Server-side timestamps

Examples: created_at, completed_at, activated_at, expires_at, last_login_time, batch status timestamps.

These are always UTC with an explicit +00:00 offset. Partners get the same value regardless of who is authenticated and regardless of what server timezone we run on.

{
"id": "exp_8f2a",
"created_at": "2026-01-15T09:30:00+00:00",
"completed_at": "2026-01-15T09:32:15+00:00"
}

Convert to your own timezone client-side if you need to display them locally.


2. Measurement data with a known site timezone

Examples: vehicle counts (/api/v1/traffic/data/search records), voltage readings, temperature readings, "first vehicle" / "last vehicle" timestamps on a site.

Every measuring site has a configured timezone (e.g. Europe/Berlin, America/New_York). Measurement timestamps for a site are returned in that site's local time, with the matching offset attached:

Site in Europe/Berlin (CET, +01:00 in winter)
{
"timestamp": "2026-01-15T10:00:00+01:00",
"count": 42,
"channel": 1
}
Same data shape, site in America/New_York (EST, -05:00)
{
"timestamp": "2026-01-15T10:00:00-05:00",
"count": 42,
"channel": 1
}

The offset makes it unambiguous: 10:00 +01:00 and 10:00 -05:00 are six hours apart in real time, but both display as "10:00 in the morning" at their respective sites.

:::tip Why site-local instead of UTC? Most analytical use cases ("how many vehicles passed at 7am rush hour?") care about local time. Returning site-local with an explicit offset gives you both — read it as wall-clock, or parse with the offset for absolute-instant math. :::

Daylight saving

The offset embedded in each timestamp reflects whatever was in effect at that moment. A 2026-07-15 summer reading for Europe/Berlin returns +02:00 (CEST); the same site in winter returns +01:00 (CET). No special handling required — your ISO 8601 parser handles it automatically.


3. The "no offset" case (rare)

A small subset of data — web-import data not linked to any measuring site — has no known timezone. For those records the timestamp is returned as a bare ISO 8601 string with no offset:

{
"timestamp": "2026-01-15T10:00:00",
"count": 120,
"channel": 0
}

Treat this as wall-clock time in an unknown timezone. Display it as-is. Do not convert it to UTC or to a local timezone — you'd be inventing data.

You can test for this in code by checking whether the string ends with Z, +HH:MM, or -HH:MM. If it doesn't, it's a no-offset value.


4. Sending timestamps in (filters)

When you send timestamps to the API — for example as start_date / end_date filters on /api/v1/traffic/data/search — you can use either format and the meaning differs:

Input formatMeaning
2026-03-01T00:00:00+01:00 (with offset)An absolute instant. Each site's records are filtered relative to the equivalent instant in its own local time.
2026-03-01T00:00:00 (no offset)Wall-clock time at every site. "Midnight at every site" regardless of timezone.

Pick the format that matches your use case:

  • Reporting a single moment across sites? Send an offset.
  • Asking "what happened during business hours at every site"? Send without an offset.

5. Parsing recipes

Most languages and SDKs parse ISO 8601 with offset out of the box.

Python (stdlib, 3.11+)
from datetime import datetime
datetime.fromisoformat("2026-01-15T10:00:00+01:00")
# → datetime.datetime(2026, 1, 15, 10, 0, tzinfo=...timezone(timedelta(hours=1)))

# No offset → naive datetime
datetime.fromisoformat("2026-01-15T10:00:00")
# → datetime.datetime(2026, 1, 15, 10, 0) ← tzinfo is None
JavaScript
new Date("2026-01-15T10:00:00+01:00");
// → 2026-01-15T09:00:00.000Z (parsed as absolute instant)

// No offset → JS treats it as local browser time. Be careful.
new Date("2026-01-15T10:00:00");
// → varies depending on the browser's timezone

In JavaScript, if you want strict "wall-clock" handling for the no-offset case, use a library like Luxon or Day.js:

Luxon
import {DateTime} from 'luxon';
DateTime.fromISO("2026-01-15T10:00:00", {setZone: true});

Summary checklist

  • ✅ All API timestamps are ISO 8601.
  • ✅ Server metadata → UTC (+00:00).
  • ✅ Measurement data with a site → site-local with the site's offset.
  • ✅ Measurement data without a site → bare ISO, treat as wall-clock.
  • ✅ DST handled automatically by the offset embedded in each value.
  • ✅ Filter inputs accept either format — pick the one that matches "absolute instant" vs "wall-clock at each site".