tallge

Reference / Date and time formats

Date and time formats: ISO 8601, RFC 3339, Unix

Every example on this page describes the same instant: 7 October 2026, 09:30 in a zone two hours ahead of UTC, which is 07:30 UTC.

One instant, several notations

FormatExample
ISO 8601 / RFC 3339, UTC2026-10-07T07:30:00Z
ISO 8601 / RFC 3339, with offset2026-10-07T09:30:00+02:00
With milliseconds2026-10-07T07:30:00.000Z
ISO 8601 basic format20261007T073000Z
Unix seconds1791358200
Unix milliseconds1791358200000
HTTP date (IMF-fixdate)Wed, 07 Oct 2026 07:30:00 GMT
ISO week date2026-W41-3
ISO ordinal date2026-280

ISO 8601 versus RFC 3339

RFC 3339 is a strict profile of ISO 8601 for timestamps on the internet. It always has a full date, a time and an offset, with Z or ±hh:mm. A note in the RFC permits a space instead of T for readability. ISO 8601 also permits week dates, ordinal dates, reduced precision, durations such as PT90M and intervals, none of which RFC 3339 accepts.

If you produce timestamps, produce RFC 3339 in UTC with a Z. Every mainstream parser reads it, and as long as every value uses Z and the same number of fraction digits, it sorts correctly as plain text.

Unix time

Unix time counts seconds since the Unix epoch, which is timestamp 0 at midnight UTC, and pretends leap seconds do not exist. JavaScript, Java and many JSON APIs use milliseconds; most databases, shells and C APIs use seconds. A ten-digit value is seconds and a thirteen-digit value is milliseconds, for current dates.

TaskCommand
Current time in secondsdate +%s
Seconds to a readable UTC date (GNU)date -u -d @1791358200
Same on BSD and macOSdate -u -r 1791358200
ISO 8601 in UTCdate -u +%Y-%m-%dT%H:%M:%SZ
In JavaScript, secondsMath.floor(Date.now() / 1000)

A signed 32-bit counter of seconds overflows after 2147483647. Embedded systems and old file formats that store time_t in 32 bits still exist; use 64 bits.

Offsets and time zones

An offset such as +02:00 fixes one instant. A time zone such as Europe/Berlin is a named set of rules from the IANA database. The rules say which offset applies on which date and change when governments decide. Store the instant in UTC. Store the zone name separately when you need to show local time or schedule something "every day at 09:00 local".

Abbreviations like CST or IST are ambiguous: each stands for several zones on different continents. Never parse them; output them only for people to read.

Parsing traps

InputTrap
new Date("2026-10-07")date-only ISO is read as UTC midnight, which is the previous evening in zones west of UTC
new Date("2026-10-07T09:30")date-time without offset is read as local time; same string, different instant on another machine
new Date(2026, 9, 7)months are counted from 0, so 9 is October
new Date("10/07/2026")non-ISO formats are implementation-defined; current engines read this as month first, 7 October, whatever the user’s locale
TIMESTAMP '2026-10-07 09:30'in PostgreSQL, timestamp has no zone; use timestamptz, which stores UTC
2026-10-07T24:00:0024:00 as the end of a day is allowed by some editions of ISO 8601, but RFC 3339 limits hours to 00-23 and many parsers reject it; write the next day’s 00:00 instead

Daylight saving time

On the night clocks go forward, an hour of local times does not exist; on the night they go back, an hour happens twice. "Add one day" and "add 24 hours" give different results across those nights. Do calendar arithmetic in the local zone with a library that knows the rules, and duration arithmetic in UTC.

Sources