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. Common date and time formats
  2. ISO 8601 — the format you should default to
  3. RFC 3339 — ISO 8601’s stricter cousin
  4. RFC 2822 — the email and HTTP date format
  5. Unix timestamps — the developer favourite
  6. US format — MM/DD/YYYY
  7. EU / UK format — DD/MM/YYYY and DD.MM.YYYY
  8. SQL DATETIME / TIMESTAMP
  9. Cookie expiry — RFC 1123
  10. Programming-language quirks
  11. Format tokens across languages
  12. Token pitfalls
  13. What format to actually use
  14. FAQ
    1. What’s the difference between RFC 3339 and ISO 8601?
    2. What is the standard timestamp format?
    3. How do I write a date in ISO format?
    4. What’s the difference between %m and %M in strftime?
    5. Why does my date show next year’s number in late December?
    6. How do I format the current time as ISO 8601?
    7. What does the Z at the end of a timestamp mean?
  15. Tools
  16. 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.

Short answer: use ISO 8601 (2026-04-28T14:30:00Z) for anything a machine reads or stores, and a locale-aware formatter for anything a person reads.

Common date and time formats

FormatExampleUsed for
ISO 8601 / RFC 3339, UTC2026-04-28T14:30:00ZAPIs, JSON, logs
RFC 3339 with offset2026-04-28T10:30:00-04:00The same moment in Eastern time
ISO 8601 date only2026-04-28Dates with no time
RFC 5322 (email)Tue, 28 Apr 2026 14:30:00 +0000Email headers
HTTP-dateTue, 28 Apr 2026 14:30:00 GMTHTTP headers, cookies
Unix timestamp1777386600Code and databases (see the epoch converter)
SQL DATETIME2026-04-28 14:30:00MySQL, SQL Server, SQLite

Each row below has its own section with the details and pitfalls.

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. It is stricter than ISO 8601 in that the timezone is required (no naïve datetimes) and the format is fixed (four-digit year, two-digit fields). RFC 3339 also notes that applications may use a space instead of T for readability, but the T form is the one to emit.

Practically, if you emit RFC 3339 with a T separator, 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:). RFC 2822 has since been replaced by RFC 5322, which keeps the same date format. HTTP headers (Date:, Last-Modified:, Expires:) use a stricter fixed-length form, IMF-fixdate (the preferred form of HTTP-date), defined in RFC 9110 as a subset of the RFC 5322 format.

The day-of-week prefix is derivable from the date — including it is redundant, and the spec makes it optional. If you include it, it must match the date.

Gotcha: named timezones (GMT, EST, PST) are obsolete syntax in RFC 5322 (formerly RFC 2822). Senders must use numeric offsets (+0000, -0500), though receivers must still accept the old names. 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

1777386600              (seconds)
1777386600123           (milliseconds)
1777386600123456        (microseconds)
1777386600123456789     (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 after January 19, 2038.

Gotcha 2: leap seconds. Strict POSIX time ignores leap seconds — the timestamp repeats a second on insertion. Some providers, such as Google’s public time service (“leap smear”), spread the extra second across many hours instead, but plain systems do not. If you compare timestamps across leap-second boundaries on systems that handle it differently, 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: TIMESTAMPTZ (timestamp with time zone) in Postgres is timezone-aware and stored as UTC; plain TIMESTAMP (which means 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

This is the fixed-length HTTP-date form that RFC 6265 requires for the Expires attribute of Set-Cookie, with GMT mandatory. Browsers parse cookie dates leniently (RFC 6265 section 5.1.1), but 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.

Format tokens across languages

The same moment, Tuesday 2026-04-28 at 14:30:05, written with each library’s pattern letters. Python and C use strftime codes. Java and Kotlin use DateTimeFormatter.ofPattern. JavaScript has no pattern string in the language itself (Intl.DateTimeFormat takes options such as { dateStyle: "long" }), so the JavaScript column shows date-fns, with moment and Day.js alongside.

PartOutputstrftimeJava / Kotlindate-fns.NETmoment / Day.js
4-digit year2026%Yyyyy (or uuuu)yyyyyyyyYYYY
Month, 2 digits04%mMMMMMMMM
Day of month28%dddddddDD
Hour, 24-hour14%HHHHHHHHH
Hour, 12-hour02%Ihhhhhhhh
Minute30%Mmmmmmmmm
Second05%Sssssssss
AM/PMPM%paattA
Short month nameApr%bMMMMMMMMMMMM
Short weekdayTue%aEEEEEEdddddd

Month and weekday names, and %p, follow the locale. The outputs above are for English.

Token pitfalls

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 date form, as required by RFC 6265.
  5. Email or HTTP headers: RFC 5322 for email dates, HTTP-date (RFC 9110) for HTTP headers.
  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.”

FAQ

What’s the difference between RFC 3339 and ISO 8601?

RFC 3339 is a stricter profile of ISO 8601 for internet timestamps. It needs a full date, a time and an offset, such as 2026-04-28T10:30:00-04:00. ISO 8601 also allows forms like week dates and dates without a time. A valid RFC 3339 timestamp that uses the T separator is also valid ISO 8601. See RFC 3339 above.

What is the standard timestamp format?

ISO 8601, usually in its RFC 3339 form: 2026-04-28T14:30:00Z. It sorts as text, includes the time zone, and every major language can parse it.

How do I write a date in ISO format?

Year, month and day, largest first, with hyphens: 2026-04-28. Add a time after a T and end with Z for UTC or an offset like -04:00.

What’s the difference between %m and %M in strftime?

%m is the month as two digits (04) and %M is the minute (30). Java, date-fns, .NET and moment use MM for the month and mm for the minute.

Why does my date show next year’s number in late December?

The pattern almost certainly uses YYYY, the week-based year, instead of yyyy. Switch to yyyy (or uuuu in Java) and the year matches the calendar again.

How do I format the current time as ISO 8601?

In JavaScript, new Date().toISOString() gives UTC with milliseconds, such as 2026-04-28T14:30:00.000Z. In Python, datetime.now(timezone.utc).isoformat(timespec="seconds") gives 2026-04-28T14:30:00+00:00. Both are valid ISO 8601 and RFC 3339.

What does the Z at the end of a timestamp mean?

Z means UTC, an offset of zero. 2026-04-28T14:30:00Z and 2026-04-28T14:30:00+00:00 are the same moment.

Tools

TL;DR

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