Second-Precise UTC Offsets: ISO 8601 Input Now Accepts ±HH:MM:SS
Before standard time zones, cities kept their own time. In tzdata, Paris ran 9 minutes and 21 seconds ahead of Greenwich until 1911, Monrovia ran 44 minutes and 30 seconds behind until 1972, and New York was at −4:56:02 until railway time arrived in 1883. These offsets have seconds in them.
The TimeLogic API renders them exactly, and as of today it also accepts them as input. Anything that takes an ISO 8601 timestamp now understands ±HH:MM:SS offsets.
Exact offsets out
Ask for an instant in 1900 Paris:
curl "https://api.timelogicapi.com/v1/time/convert?iso=1900-06-01T12:00:00Z&tz=Europe/Paris&format=%25z|%25:z" \
-H "Authorization: Bearer $TIMELOGIC_API_KEY"
{
"unix": -2195899200,
"unix_ms": -2195899200000,
"utc": "1900-06-01T12:00:00Z",
"iso_local": "1900-06-01T12:09:21+00:09:21",
"rfc2822": "Fri, 01 Jun 1900 12:09:00 +0009",
"human": "June 1, 1900, 12:09 PM Europe/Paris",
"day_number": 6,
"day_short": "Fri",
"day_full": "Friday",
"timezone": "Europe/Paris",
"formatted": "+000921|+00:09:21"
}
iso_localcarries the full offset,+00:09:21, so the local time and the offset always describe the same instant.formatwith%zgives+000921and%:zgives+00:09:21.rfc2822can only express whole minutes, so it shows+0009and the local time at the matching minute:12:09:00.
Exact offsets in: the round trip
Now send that iso_local value straight back:
curl -G "https://api.timelogicapi.com/v1/time/convert" \
--data-urlencode "iso=1900-06-01T12:09:21+00:09:21" \
--data-urlencode "tz=UTC" \
-H "Authorization: Bearer $TIMELOGIC_API_KEY"
{
"unix": -2195899200,
"utc": "1900-06-01T12:00:00Z",
"iso_local": "1900-06-01T12:00:00+00:00",
"timezone": "Etc/UTC"
}
(Response trimmed.) Same instant, to the second. Store iso_local, send it back later, and you land exactly where you started. That holds for any offset tzdata knows:
| Zone and date (12:00 UTC) | iso_local |
|---|---|
Europe/Paris, 1900-06-01 | 1900-06-01T12:09:21+00:09:21 |
Asia/Kolkata, 1900-06-01 | 1900-06-01T17:21:10+05:21:10 |
Africa/Monrovia, 1960-06-01 | 1960-06-01T11:15:30-00:44:30 |
America/New_York, 1880-06-01 | 1880-06-01T07:03:58-04:56:02 |
Each of these goes back in as input and resolves to 12:00:00 UTC.
A tip for query strings: + means a space in a URL. Use --data-urlencode as above, or write the plus sign as %2B (iso=1900-06-01T12:09:21%2B00:09:21).
The offset is validated like the rest of the timestamp. Minutes or seconds of 60 or more (+00:09:61) return 400 INVALID_TIMESTAMP with "Invalid ISO timestamp.".
offset_seconds next to offset_minutes
The API supports local times from 0001-01-01T00:00:00 to 9999-12-31T23:59:59. When a conversion would land outside that range, the 400 INVALID_TIMESTAMP response tells you the zone and offset involved:
curl "https://api.timelogicapi.com/v1/time/convert?iso=0001-01-01T03:00:00Z&tz=America/New_York" \
-H "Authorization: Bearer $TIMELOGIC_API_KEY"
{
"error": {
"code": "INVALID_TIMESTAMP",
"message": "Local time in America/New_York falls outside years 0001-9999 (local year 0). Local results must stay between 0001-01-01T00:00:00 and 9999-12-31T23:59:59.",
"details": {
"local_year": 0,
"timezone": "America/New_York",
"offset_minutes": -296,
"offset_seconds": -17762
}
},
"request_id": "411b512a-ad5c-4408-9887-fcba63000ba9"
}
offset_secondsis exact: −17762 s is −4:56:02.offset_minutesis always a whole number, truncated toward zero (−296), the same rulerfc2822uses.offset_secondsappears only when the offset has seconds. A whole-minute offset, like Kiritimati's +14:00, reports"offset_minutes": 840alone.
Parse offset_minutes as an integer, and read offset_seconds when you need full precision.
Who this is for
- Genealogy, archives and historical datasets: timestamps from before standard time stay exact.
- Data pipelines that store
iso_localand replay it: no more rounding drift. - Anyone validating tz logic: compare your library's LMT output with the API to the second.
See Selectors for every accepted iso shape, and the convert reference to try it.