Timestamps¶
Every SDK method that takes a timestamp requires a tz-aware
datetime. Naive datetimes raise ValueError at the call site —
never silently converted, never assumed UTC.
Constructing one¶
from datetime import datetime, timezone
start = datetime(2024, 1, 1, tzinfo=timezone.utc)
end = datetime(2024, 1, 2, tzinfo=timezone.utc)
For non-UTC zones:
from datetime import datetime
from zoneinfo import ZoneInfo
start = datetime(2024, 1, 1, 8, 0, tzinfo=ZoneInfo("America/Los_Angeles"))
The SDK serializes to UTC ISO-8601 internally regardless of the input zone.
Wire formats — two flavors¶
The server is inconsistent about timestamp formats across endpoints (RESEARCH §2 documents which use which):
- Alarms / events / positions — Unix milliseconds.
- Reports — ISO-8601 strings.
The SDK picks the right format per endpoint. You always pass the same
Python datetime; the SDK handles the conversion.
Parsing server responses¶
Returned model fields use datetime for any timestamp. They are
tz-aware (UTC). Compare them with your own tz-aware values:
report = client.reports.heatmap(start=start, end=end, tag_uids=["t-1"])
if report.created_at > start:
...
Anti-patterns¶
# WRONG — naive datetime raises ValueError
start = datetime(2024, 1, 1)
client.alarms.list(start=start, end=end)
# WRONG — int seconds; the SDK only accepts datetime
client.alarms.list(start=1704067200, end=end)
These are intentional. Naive datetimes are a frequent source of silent off-by-N-hour bugs; the SDK refuses to guess.