RFC 3339 vs ISO 8601

· formats

Almost the same, but not quite a subset in either direction. If you are writing an API, target the overlap.

ISO 8601 is a large, permissive international standard covering dates, times, durations, intervals and recurrence. RFC 3339 is a short internet specification that profiles the parts relevant to timestamps and pins down what ISO leaves optional.

For interchange, RFC 3339 is almost always the right target.

What RFC 3339 requires

2024-03-10T06:00:00Z
2024-03-10T11:30:00+05:30
2024-03-10T06:00:00.123456Z

Mandatory: a four-digit year, two-digit month and day, T or a space separator, hours, minutes, seconds, and an offset or Z. Fractional seconds are optional with unlimited digits.

The important constraint: the offset is not optional. ISO 8601 permits a naked local time with no zone information; RFC 3339 does not. This single rule eliminates the most common source of timestamp ambiguity.

Where they differ

ISO 8601 RFC 3339
Offset required No Yes
Space instead of T No Yes (permitted)
Lowercase t / z No Yes (permitted)
-00:00 (unknown offset) Prohibited Allowed, with meaning
24:00:00 Allowed Prohibited
Week dates (2024-W10-7) Allowed Not covered
Ordinal dates (2024-070) Allowed Not covered
Basic format (20240310T060000Z) Allowed Not covered
Durations (P1Y2M) Allowed Not covered
Leap second :60 Allowed Allowed

Neither is a strict subset of the other. RFC 3339 permits a space separator and -00:00, both of which ISO 8601 forbids; ISO 8601 permits week dates and 24:00:00, which RFC 3339 does not cover or forbids.

The -00:00 case

RFC 3339 gives -00:00 a distinct meaning: the instant is known but the local offset is not. +00:00 asserts UTC; -00:00 asserts “UTC, and we do not know what the local clock read”.

The distinction is rarely used and inconsistently implemented. Accept it on input, do not emit it.

The safe intersection

For anything crossing a system boundary, emit:

YYYY-MM-DDTHH:MM:SSZ

Uppercase T, uppercase Z, UTC, no fractional seconds unless you need them. This is valid under both standards and parses everywhere without configuration.

If you need sub-second precision, three or six digits are the widely supported choices:

2024-03-10T06:00:00.123Z
2024-03-10T06:00:00.123456Z

Note that some parsers accept only three. Nanosecond precision (nine digits) is legal but poorly supported outside Go and Rust.

What other specifications use

  • JSON Schema format: "date-time" — RFC 3339.
  • OpenAPI format: date-time — RFC 3339.
  • HTTP Date headers — neither; RFC 7231 uses its own format with a literal GMT.
  • Email Date headers — RFC 5322, the Sun, 10 Mar 2024 06:00:00 +0000 form.
  • XML Schema xs:dateTime — ISO 8601, with its own restrictions.
  • JWT exp/iat/nbf — not a string at all; Unix seconds as a number.

So an API that speaks JSON should emit RFC 3339, but the HTTP headers wrapping it use a different format entirely, and any JWT inside uses integers. All three in one response is normal.

Language support

new Date().toISOString();            // 2024-03-10T06:00:00.000Z — RFC 3339 valid
from datetime import datetime, timezone
datetime.now(timezone.utc).isoformat()    # '+00:00' rather than 'Z'
# Python's fromisoformat only accepted a trailing 'Z' from 3.11 onwards
time.Now().UTC().Format(time.RFC3339)     // Go names it explicitly

Python’s default output uses +00:00 where JavaScript uses Z. Both are valid RFC 3339 and represent the same instant, but string comparison between them fails — never compare timestamps as strings.

Practical rules

  1. Emit YYYY-MM-DDTHH:MM:SSZ unless you have a specific reason not to.
  2. Always include an offset. This is the rule that matters most.
  3. Parse leniently — accept a space separator, lowercase t/z, and any number of fractional digits.
  4. Compare instants after parsing, never as strings.
  5. Do not use week dates, ordinal dates or 24:00:00 in interchange.

See ISO 8601 explained for the fuller treatment of the underlying standard. The converter shows the RFC 3339 form of any timestamp in the ISO 8601 row.

Related guides