Dates are written differently around the world — "04/04/26" means April 4 in Japan, April 26 in the US, or even May 4 in Europe depending on convention. ISO 8601 is the international standard that eliminates this ambiguity by defining a single, unambiguous format for dates and times.
This guide covers everything from the basic syntax to timezones, durations, and practical usage in JavaScript, Python, PHP, and SQL.
What is ISO 8601?
ISO 8601 is an international standard published by the International Organization for Standardization (ISO) defining how to represent dates and times. First issued in 1988, the current version is from 2019.
The core design principle is largest-to-smallest ordering: year, then month, then day, then hour, minute, second. This makes ISO 8601 strings naturally sortable alphabetically and removes all geographic ambiguity.
Where ISO 8601 is used
- REST APIs: JSON datetime fields in API responses
- Databases: MySQL DATETIME, PostgreSQL TIMESTAMPTZ
- File names & logs: Sortable timestamps (e.g.,
2026-04-04_backup.sql) - HTML <time> element: The
datetimeattribute - Calendar apps: iCal (.ics) format
- Git commits & CI/CD: Standard timestamp format
Basic Format: Dates, Times, and Datetimes
Dates
ISO 8601 dates are always in year-month-day order.
# Extended format (hyphen-separated) — most common 2026-04-04 # Basic format (no separators) 20260404 # Year and month only 2026-04 # Year only 2026
Fields are fixed-width and zero-padded: months and days are always two digits (April → 04).
Times
# Hour:Minute:Second (extended) 14:30:00 # With fractional seconds (period or comma) 14:30:00.500 ← 500 milliseconds 14:30:00,500 ← comma is also valid # Basic format 143000
Combined Datetime (most important)
Dates and times are combined using the letter T as a separator.
2026-04-04T14:30:00 # With milliseconds 2026-04-04T14:30:00.500 # With timezone (covered in next section) 2026-04-04T14:30:00Z 2026-04-04T14:30:00+09:00
This T-separated format is also used by RFC 3339 (the internet-specific derivative), and is the default output of most programming language datetime functions.
Timezone Notation: Z and ±HH:MM
A datetime without a timezone offset is ambiguous — it only indicates local time without specifying which timezone. For APIs, databases, and cross-system data exchange, always include a timezone designator.
UTC (Coordinated Universal Time)
2026-04-04T14:30:00Z
The trailing Z stands for "Zulu time" and means UTC (offset +00:00).
UTC Offsets
# Japan Standard Time (JST = UTC+9) 2026-04-04T23:30:00+09:00 # US Eastern Daylight Time (EDT = UTC-4) 2026-04-04T10:30:00-04:00 # India Standard Time (IST = UTC+5:30) 2026-04-04T20:00:00+05:30
The offset like +09:00 means "this time is 9 hours ahead of UTC."
Z vs +00:00
Both represent the same instant in time, but conventions differ:
- Z: Common in API responses, logs, and system communication — concise and unambiguous
- +00:00: Sometimes used when specifically referring to London time (no daylight saving)
JavaScript's Date.toISOString() outputs Z by default.
Week Numbers & Ordinal Dates
ISO Week Date
# Format: YYYY-Www-D (W = Week, D = day of week: 1=Mon, 7=Sun) 2026-W14-6 ← Saturday of week 14, 2026 # Week only 2026-W14
ISO weeks start on Monday. Week 1 (W01) is defined as the week containing the first Thursday of the year. This means January 1st might belong to the last week of the previous year.
Ordinal Dates
# Format: YYYY-DDD (DDD = day of year) 2026-094 ← 94th day of 2026 (= April 4)
Useful in log processing, astronomical calculations, or any context where "day of year" is more natural than month/day.
Durations
ISO 8601 also standardizes how to express lengths of time. Duration strings start with P (for "Period").
# General syntax P[nY][nM][nW][nD]T[nH][nM][nS] # Examples P1Y ← 1 year P3M ← 3 months P7D ← 7 days PT2H30M ← 2 hours 30 minutes P1Y2M3DT4H5M ← 1 year 2 months 3 days 4 hours 5 minutes PT30S ← 30 seconds
The T separates date components (Y/M/W/D) from time components (H/M/S). It's required when any time component is present.
Real-world usage
- JWT expiration:
PT1H(1 hour) - Cache TTL:
PT5M(5 minutes) - HTML <video> duration attribute:
PT1M30S(1 minute 30 seconds) - iCal DURATION property:
P1D(1 day)
Intervals and Repeating Intervals
Time Intervals
# Start/End 2026-04-01T00:00:00Z/2026-04-30T23:59:59Z # Start/Duration 2026-04-01T00:00:00Z/P1M # Duration/End P1M/2026-04-30T23:59:59Z
Repeating Intervals
# Format: R[n]/[interval] R5/2026-04-04T09:00:00Z/PT1H ← 5 times, every hour from 09:00 UTC R/2026-04-04T09:00:00Z/P1W ← repeat weekly forever (R alone = infinite)
ISO 8601 in Programming Languages
JavaScript / TypeScript
// Get current datetime as ISO 8601 (UTC)
const now = new Date().toISOString();
// → "2026-04-04T14:30:00.000Z"
// Parse an ISO 8601 string
const date = new Date("2026-04-04T14:30:00+09:00");
// Format for display using Intl.DateTimeFormat
const formatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit',
timeZone: 'Asia/Tokyo'
});
console.log(formatter.format(date));
Python
from datetime import datetime, timezone, timedelta
# Current UTC time in ISO 8601
now_utc = datetime.now(timezone.utc)
print(now_utc.isoformat())
# → "2026-04-04T14:30:00.000000+00:00"
# With JST offset
jst = timezone(timedelta(hours=9))
now_jst = datetime.now(jst)
print(now_jst.isoformat())
# → "2026-04-04T23:30:00.000000+09:00"
# Parse ISO 8601 (Python 3.7+)
dt = datetime.fromisoformat("2026-04-04T14:30:00+09:00")
# Z suffix supported in Python 3.11+
dt = datetime.fromisoformat("2026-04-04T14:30:00Z")
PHP
format(DateTime::ATOM);
// → "2026-04-04T14:30:00+00:00"
// Parse ISO 8601
$dt = new DateTime("2026-04-04T14:30:00+09:00");
// Carbon (common in Laravel)
$now = Carbon\Carbon::now('Asia/Tokyo')->toIso8601String();
?>
SQL (MySQL / PostgreSQL)
-- MySQL: format current datetime as ISO 8601 SELECT DATE_FORMAT(NOW(), '%Y-%m-%dT%H:%i:%sZ') AS iso8601; -- PostgreSQL: ISO 8601 with timezone SELECT NOW()::timestamptz AT TIME ZONE 'UTC'; -- or SELECT to_char(NOW() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"');
ISO 8601 in HTML: The <time> Element
HTML5's <time> element lets you embed machine-readable datetimes in your markup using the datetime attribute. This helps search engines, screen readers, and other tools interpret dates correctly.
<!-- Date only --> <time datetime="2026-04-04">April 4, 2026</time> <!-- Full datetime with timezone --> <time datetime="2026-04-04T14:30:00+09:00">April 4, 2026 at 2:30 PM JST</time> <!-- Blog article publish date --> <article> <h1>Article Title</h1> <p>Published: <time datetime="2026-04-04" pubdate>April 4, 2026</time></p> </article>
Google's structured data (Schema.org) also recommends ISO 8601 for date fields:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"datePublished": "2026-04-04T09:00:00+09:00",
"dateModified": "2026-04-04T12:00:00+09:00"
}
</script>
Common Mistakes to Avoid
1. Missing timezone
# Ambiguous — which timezone is 14:30? 2026-04-04T14:30:00 # Clear — UTC 2026-04-04T14:30:00Z # Clear — JST 2026-04-04T14:30:00+09:00
Always include a timezone offset in API responses and stored data. Omitting it is a common source of off-by-hours bugs when servers are in different timezones.
2. Wrong separators
# Not ISO 8601 2026/04/04 14:30:00 # Correct 2026-04-04T14:30:00
3. Wrong order (US-style)
# Wrong 04-04-2026 # Correct (largest unit first) 2026-04-04
4. Missing zero-padding
# Wrong 2026-4-4 # Correct 2026-04-04
FAQ
Q. What's the difference between ISO 8601 and RFC 3339?
RFC 3339 is a stricter subset of ISO 8601 designed for internet protocols. Key differences: RFC 3339 requires a timezone designator (no omitting it), doesn't allow a space in place of T, and restricts some edge cases. In practice, most APIs labeled "ISO 8601" actually mean RFC 3339 format. The two are interchangeable for everyday use.
Q. Does JavaScript's Date object fully support ISO 8601?
Mostly yes, but with a gotcha: date-only strings like 2026-04-04 are parsed as UTC midnight by most browsers, not local midnight. To avoid surprises, always use the full datetime form 2026-04-04T00:00:00 when parsing, or use a library like date-fns, Day.js, or Luxon.
Q. Is Z the same as +00:00?
Yes — both represent UTC. Z is simply a shorthand notation. Some strict parsers accept only one form, so check your target environment. Most modern parsers handle both.
Q. How do I quickly convert between date formats?
Use Devryo's Date Format Converter to instantly convert between ISO 8601, RFC 2822, Unix timestamps, and 9 other formats. No login required.
Summary
ISO 8601 is the universal language of dates and times in software. The key rules to remember:
- Format:
YYYY-MM-DDTHH:mm:ss— T separator, zero-padded fields - Timezone: Always include Z or ±HH:MM in cross-system data
- Order: Year → Month → Day → Hour → Minute → Second (largest first)
Need to convert date formats? Try the Date Format Converter or Unix Timestamp Converter — both free, no login needed.