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".