ISO-8601 Time Zone Traps: No Offset, Date-Only and Impossible Dates
The ISO-8601 converter applies the rules below. Where they differ from what a runtime does, the converter picks the stricter behaviour and says so.
Three shapes of input
| Input | Meaning | Converter output |
|---|---|---|
2026-10-07T12:00:00Z or ...+05:30 | An exact instant | One epoch value |
2026-10-07 | A calendar date; read as UTC midnight (the ECMAScript rule) | One epoch value |
2026-10-07T12:00:00 | A wall-clock time in an unknown zone | Two values: as UTC, and as your local time |
The third row is the source of most timestamp bugs. The ISO format treats a time with no offset as local time, but not every parser agrees, and the receiving system's idea of "local" may not be yours. A string that will leave your machine should always carry Z or an offset.
The date-only exception
In JavaScript, new Date("2026-10-07") is UTC midnight, but new Date("2026-10-07T00:00:00") is local midnight. Two strings that look the same except for a time part resolve to different instants on any machine whose zone is not UTC.
Impossible dates
2026-02-30 is not a date. Many runtimes accept it and return March 2. The converter rejects it with the number of days that month actually has, since a rolled-over date is a silent change of data. It likewise rejects month 13 and hours above 23.
Offsets and zones are not the same thing
+05:30 is an offset: a fixed difference from UTC at that instant. It does not say "Asia/Kolkata", and it does not tell you what the offset will be next month, because daylight-saving rules live with zone names. Store the instant (UTC or epoch) and, if you need to show local wall time later, store the zone name too.