ISO 8601 Date and Time Format: A Practical Guide
A cheat sheet for ISO 8601: dates, week and ordinal dates, times, UTC offsets, durations and intervals, how RFC 3339 differs, common mistakes, and code examples.
ISO 8601 is the international standard for writing dates and times as text. Its core rule is largest unit first: 2026-10-22 for a date, 14:30:00 for a time, and 2026-10-22T14:30:00Z or 2026-10-22T16:30:00+02:00 for an exact moment. The fixed order and zero-padding make the strings unambiguous across languages and let them sort correctly as plain text.
The standard is published by ISO; the current edition is ISO 8601-1:2019 (with an amendment in 2022), plus ISO 8601-2 for extensions. Most software actually implements RFC 3339, a stricter subset described below.
Calendar dates
| Form | Example | Notes |
|---|---|---|
| Extended | 2026-10-22 | year-month-day, the form almost everyone uses |
| Basic | 20261022 | same, without separators |
| Year and month | 2026-10 | reduced precision |
| Year | 2026 |
Four-digit years and two-digit months and days are required: 2026-1-5 is not ISO 8601; 2026-01-05 is.
Week dates and ordinal dates
| Form | Example | Meaning |
|---|---|---|
| Week date | 2026-W44-3 | ISO year 2026, week 44, day 3 (Wednesday) = 28 October 2026 |
| Week | 2026-W44 | the whole week, Monday 26 October to Sunday 1 November 2026 |
| Ordinal date | 2026-305 | the 305th day of 2026 = 1 November 2026 |
ISO weeks start on Monday (day 1) and end on Sunday (day 7). Week 1 is the week that contains the year’s first Thursday — equivalently, the week containing 4 January. A year therefore has 52 or 53 ISO weeks; 2020 and 2026 have 53, and the next is 2032. The current week is on the week number page.
Ordinal dates count days from 1 January = day 001. They are common in logistics, manufacturing batch codes and some scientific data.
Times
| Form | Example | Notes |
|---|---|---|
| Hours and minutes | 14:30 | 24-hour clock, always |
| With seconds | 14:30:00 | |
| Fractional seconds | 14:30:00.250 | a comma is also allowed by ISO 8601 |
| Basic format | 143000 | |
| Midnight, start of day | 00:00 | |
| Midnight, end of day | 24:00 | removed in the 2019 edition, reinstated by the 2022 amendment |
There is no a.m./p.m. in ISO 8601. For converting 12-hour times, see 24-Hour Time and Military Time.
UTC, offsets and combined date-times
| Form | Example | Meaning |
|---|---|---|
| UTC | 2026-10-22T14:30:00Z | Z means zero offset (UTC); military “Zulu” |
| Positive offset | 2026-10-22T16:30:00+02:00 | local time 2 hours ahead of UTC — same instant as above |
| Negative offset | 2026-10-22T10:30:00-04:00 | 4 hours behind UTC — same instant again |
| Fractional-hour offset | 2026-10-22T20:00:00+05:30 | India — same instant again |
| No offset | 2026-10-22T14:30:00 | local time, zone unspecified |
| Basic format | 20261022T143000Z |
The T separates date and time. The offset is the local time minus UTC: to get UTC, subtract it (16:30+02:00 → 14:30Z).
Durations and intervals
Durations start with P (“period”). Date components come first; T introduces the time components.
| Duration | Meaning |
|---|---|
P1D | 1 day |
PT2H | 2 hours |
P1DT2H | 1 day and 2 hours |
PT30M | 30 minutes (note T: P30M is 30 months) |
P1Y2M10DT2H30M | 1 year, 2 months, 10 days, 2 hours, 30 minutes |
P2W | 2 weeks |
PT0.5S | half a second |
Intervals join two parts with a slash:
| Interval | Meaning |
|---|---|
2026-10-22T09:00Z/2026-10-22T17:00Z | start and end |
2026-10-22/P3D | start and duration |
PT2H/2026-10-22T12:00Z | duration and end |
R5/2026-10-22T09:00Z/P1D | repeat 5 times, daily |
Calendar durations like P1M are not a fixed number of seconds — a month after 31 January needs a rule — so libraries differ. For date arithmetic, the time calculator does the work.
RFC 3339: the internet profile
RFC 3339 defines a strict subset of ISO 8601 for internet protocols, and most APIs, JSON schemas and logging formats follow it. The main differences:
| ISO 8601 | RFC 3339 | |
|---|---|---|
| Full date and time required | no (reduced precision allowed) | yes: YYYY-MM-DDThh:mm:ss |
| Offset required | no | yes: Z or ±hh:mm |
Basic format (20261022T143000Z) | allowed | not allowed |
| Week and ordinal dates, durations, intervals | allowed | not covered |
Space instead of T | not in the standard form | permitted “for the sake of readability” |
Lower-case t and z | allowed | allowed, upper case recommended |
-00:00 offset | no special meaning | means “UTC known, local offset unknown” |
Leap second 23:59:60 | allowed | allowed |
A timestamp like 2026-10-22T14:30:00Z is valid under both.
Why YYYY-MM-DD sorts correctly
Because the units go from largest to smallest and every field has a fixed width, alphabetical order equals chronological order. 2026-09-30 < 2026-10-01 < 2026-10-22 as strings and as dates. 10/22/2026 and 22/10/2026 do not sort, and do not even agree with each other.
The guarantee holds only when all strings use the same form and the same offset. 2026-10-22T23:00:00-05:00 sorts before 2026-10-23T01:00:00Z but is actually three hours later. Normalize to UTC before sorting or comparing as text.
Common mistakes
- Treating an offset as a time zone.
-04:00says how far a timestamp is from UTC at that instant; it does not say “New York”. New York is −04:00 in summer and −05:00 in winter. If you need future local times to follow daylight saving rules, store the IANA zone name (for exampleAmerica/New_York) alongside the time. - Leaving off the offset.
2026-10-22T10:00is local time in an unknown zone. In JavaScript,new Date("2026-10-22T10:00")is interpreted in the computer’s own zone, while the date-onlynew Date("2026-10-22")is interpreted as UTC midnight — two different rules in one function. - Mixing the ISO week-year with the calendar year. Around New Year the two differ. Thursday 31 December 2026 is
2026-W53-4, and Friday 1 January 2027 is2026-W53-5; ISO week 1 of 2027 begins on Monday 4 January 2027. In the other direction, Monday 29 December 2025 is2026-W01-1. Format patterns make this easy to get wrong: in many librariesYYYYor%Gis the week-year andyyyyor%Yis the calendar year. - Using
P30Mfor 30 minutes. It means 30 months; minutes needPT30M. - Dropping leading zeros.
2026-1-5or9:05are not ISO 8601.
Producing ISO 8601 in code
JavaScript
new Date().toISOString();
// "2026-10-22T14:30:00.000Z" — always UTC, with milliseconds and Z
toISOString() always converts to UTC. There is no built-in method for a local time with offset or an ISO week number.
Python
from datetime import datetime, timezone
datetime.now(timezone.utc).isoformat()
# '2026-10-22T14:30:00.123456+00:00'
datetime(2026, 10, 22, 14, 30).isoformat()
# '2026-10-22T14:30:00' — naive: no offset
datetime.fromisoformat("2026-10-22T14:30:00Z") # accepts 'Z' since Python 3.11
datetime(2027, 1, 1).isocalendar() # (year=2026, week=53, weekday=5)
Python writes UTC as +00:00, not Z. Use an aware datetime (with tzinfo) whenever the value represents a real instant.
SQL
-- PostgreSQL
SELECT to_char(now() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"');
SELECT to_char(date '2027-01-01', 'IYYY-"W"IW-ID'); -- 2026-W53-5
-- MySQL
SELECT DATE_FORMAT(UTC_TIMESTAMP(), '%Y-%m-%dT%H:%i:%sZ');
Shell (GNU date)
date -Iseconds # 2026-10-22T16:30:00+02:00 (local, with offset)
date -u +%Y-%m-%dT%H:%M:%SZ # 2026-10-22T14:30:00Z (portable)
date -d 2027-01-01 +%G-W%V-%u # 2026-W53-5
-I and -d are GNU coreutils options; the explicit +%Y-%m-%dT%H:%M:%SZ format string is the portable choice. For converting between ISO timestamps and seconds since 1970, see Unix Time Explained and the Unix time converter.
Sources
- ISO 8601-1:2019 — Date and time — Representations for information interchange
- RFC 3339 — Date and Time on the Internet: Timestamps
- Python documentation — datetime
- MDN — Date.prototype.toISOString()
Dates, offsets and astronomical times quoted here are computed with the same code that powers the site's tools — see data sources and methods. Found an error? Tell us.