Skip to content
100% in your browser. Nothing you paste is uploaded — all processing runs locally. Read more →

Date and time formats — working reference

On this page
  1. ISO 8601 — the format you should default to
  2. RFC 3339 — ISO 8601’s stricter cousin
  3. RFC 2822 — the email and HTTP date format
  4. Unix timestamps — the developer favourite
  5. US format — MM/DD/YYYY
  6. EU / UK format — DD/MM/YYYY and DD.MM.YYYY
  7. SQL DATETIME / TIMESTAMP
  8. Cookie expiry — RFC 1123
  9. Programming-language quirks
  10. What format to actually use
  11. Tools
  12. TL;DR

There are at least nine date formats in common use, three of them ambiguous, and most software gets at least one of them wrong on edge cases. This page is the reference I keep rebuilding by hand — every format, with an example, the systems that emit it, and the gotchas.

ISO 8601 — the format you should default to

2026-04-28T14:30:00Z
2026-04-28T14:30:00+09:00
2026-04-28T14:30:00.123456Z

The international standard. Year-month-day, time, then a timezone suffix (Z for UTC or ±HH:MM for an offset). Sortable as plain strings — alphabetical sort matches chronological sort. Unambiguous across locales.

Use it as your default. Every modern API, log format, and programming language supports it.

Common variants:

Gotcha: the T separator is required by the spec, but many systems accept a space (2026-04-28 14:30:00Z) for human readability. Don’t write parsers that depend on this — the spec requires T.

RFC 3339 — ISO 8601’s stricter cousin

2026-04-28T14:30:00Z
2026-04-28T14:30:00.123-05:00

A profile of ISO 8601 used in JSON / HTTP / many APIs. Stricter than ISO 8601 in two ways:

  1. The T separator is required (no space).
  2. The timezone is required (no naïve datetimes).

Practically, if you emit RFC 3339 you also emit valid ISO 8601. If you emit ISO 8601, you might not be RFC 3339 compliant.

Use it for: JSON APIs, OpenAPI specs, log files. JavaScript’s new Date().toISOString() produces RFC 3339 output.

RFC 2822 — the email and HTTP date format

Tue, 28 Apr 2026 14:30:00 +0000
Tue, 28 Apr 2026 14:30:00 GMT

Originally for email headers (Date:) but now also in HTTP headers (Date:, Last-Modified:, Expires: — though HTTP technically uses RFC 7231, which is RFC 2822 with restrictions).

The day-of-week prefix is derivable from the date — including it is redundant, but the spec requires it.

Gotcha: named timezones (GMT, EST, PST) are technically allowed but discouraged. RFC 2822 prefers numeric offsets (+0000, -0500). Some parsers reject named timezones; some accept them but guess wrong (does “EST” mean Eastern Standard Time or Australian Eastern Standard Time?).

Use it for: email headers, HTTP headers, legacy systems that require it. Avoid for new APIs.

Unix timestamps — the developer favourite

1745855400              (seconds)
1745855400123           (milliseconds)
1745855400123456        (microseconds)
1745855400123456789     (nanoseconds)

Seconds since 1970-01-01T00:00:00Z. The most compact, sortable, and unambiguous representation. No timezone needed (it’s always UTC).

The big four resolutions:

Spotting which one you have: count digits. If a “timestamp” has 13 digits, it’s milliseconds. If 16, microseconds. The conversion is trivial — just divide by 1000.

The epoch converter auto-detects which resolution you’ve pasted.

Gotcha 1: Y2038. Signed 32-bit Unix timestamps overflow on 2038-01-19. Most modern systems use 64-bit, but check yours if you have any expiry dates >30 years out.

Gotcha 2: leap seconds. Strict POSIX time ignores leap seconds — the timestamp jumps backward by 1 on insertion. Most operating systems smear the leap second across nearby seconds (Google’s “leap smear”) to avoid this. If you compare timestamps across leap-second boundaries on incompatible systems, you can be off by 1 second.

US format — MM/DD/YYYY

4/28/2026
04/28/2026
4-28-2026

US default. Used in form inputs, news copy, banking statements.

Gotcha: ambiguous against EU format. 04/05/2026 is April 5 (US) or May 4 (EU). Without context you can’t tell. Never use slash-format dates in APIs or logs. Reserve them for human-formatted output where the locale is known.

EU / UK format — DD/MM/YYYY and DD.MM.YYYY

28/04/2026   (UK, France, Australia)
28.04.2026   (Germany, Russia)
28-04-2026   (Netherlands)

Day-month-year. Aligns with how dates are spoken in most European languages.

Gotcha: same ambiguity as US format. Reserve for human display.

SQL DATETIME / TIMESTAMP

2026-04-28 14:30:00          (MySQL DATETIME)
2026-04-28 14:30:00.123456+00 (Postgres TIMESTAMPTZ)
2026-04-28 14:30:00.000      (SQL Server)

Most relational databases accept ISO 8601 input but emit a locale-specific or vendor-specific format on display.

Critical distinction: TIMESTAMP in Postgres is timezone-aware and stored as UTC; TIMESTAMP WITHOUT TIME ZONE is naïve and stored literally. MySQL DATETIME is always naïve; MySQL TIMESTAMP is auto-converted to UTC on insert and back to the connection’s timezone on read. Know which one your column is.

Use it for: database columns. Convert to ISO 8601 at the API boundary.

Tue, 28 Apr 2026 14:30:00 GMT

Looks identical to RFC 2822 except GMT is mandatory. Browsers’ Set-Cookie parsers vary on what they accept; always emit exactly this form.

Programming-language quirks

LanguageCommon outputNotes
JavaScriptnew Date().toISOString()RFC 3339 with millisecond precision
Pythondatetime.isoformat()ISO 8601, optional timezone
JavaInstant.toString()RFC 3339, nanosecond precision
Gotime.Now().Format(time.RFC3339)Strict RFC 3339
RubyTime.now.iso8601ISO 8601, optional fractional seconds
C#DateTime.UtcNow.ToString("o")”round-trip” format ≈ RFC 3339
Rustchrono::Utc::now().to_rfc3339()RFC 3339
SQLvaries — see abovevaries

The “default toString” of each language often emits something different — Date.toString() in JavaScript gives a human-locale form (Tue Apr 28 2026 ...) that is not ISO 8601 and not parseable back to a Date in all engines. Always use the explicit ISO method.

What format to actually use

A short decision tree:

  1. API request/response: ISO 8601 / RFC 3339, UTC, millisecond precision. Fight for this in code review.
  2. Log files: ISO 8601 with timezone. Sortable as text, debuggable from anywhere.
  3. Database: language-native timestamp type, configured to UTC. Convert on the way out.
  4. Cookies: RFC 1123 (browser-mandated).
  5. Email or HTTP headers (legacy): RFC 2822.
  6. Filename or URL: ISO 8601 date-only, no spaces or colons. 2026-04-28-myreport.json sorts and reads cleanly.
  7. Human-facing display: format for the user’s locale (Intl.DateTimeFormat in JavaScript, babel.dates in Python). Never expose ISO 8601 directly to an end user — they want “April 28, 2026,” not “2026-04-28T14:30:00Z.”

Tools

TL;DR

When in doubt, paste the value into the epoch converter to see what it actually decodes as.