RFC 2822 Date Format: The Email Standard
What the RFC 2822 date format is, where you'll encounter it, how it differs from ISO 8601, and how to parse and generate it in JavaScript, Python, and other languages.
What Is RFC 2822?
If you've ever looked at the raw headers of an email, you've seen an RFC 2822 date:
Date: Sat, 29 Jun 2024 14:30:00 -0400 RFC 2822 (formally titled "Internet Message Format") is the standard that defines the format of email messages. Section 3.3 specifies how dates and times should be represented in email headers. The format looks like this:
day-of-week, DD Mon YYYY HH:MM:SS ±HHMM
Examples:
Sat, 29 Jun 2024 14:30:00 -0400
Thu, 01 Jan 2026 00:00:00 +0000
Mon, 15 Jul 2024 09:45:30 +0530 The format is human-readable by design — it was created in an era when people regularly read raw email headers. Unlike ISO 8601, which optimizes for machines and sorting, RFC 2822 optimizes for a human scanning a message header and immediately understanding when it was sent.
The Format, Piece by Piece
Sat, 29 Jun 2024 14:30:00 -0400
│ │ │ │ │ │ │ └─── UTC offset (±HHMM, no colon)
│ │ │ │ │ │ └─────── seconds (00–59)
│ │ │ │ │ └────────── minutes (00–59)
│ │ │ │ └───────────── hours (00–23, 24-hour clock)
│ │ │ └────────────────── four-digit year
│ │ └────────────────────── three-letter month abbreviation
│ └───────────────────────── day of month (1 or 2 digits)
└────────────────────────────── day of week (optional, 3 letters + comma) Day of week — Optional but almost always present. Three-letter English abbreviation: Mon, Tue, Wed, Thu, Fri, Sat, Sun. Followed by a comma and a space.
Day of month — One or two digits. Both 9 and 09 are valid for the 9th. No leading zero is required (unlike ISO 8601).
Month — Three-letter English abbreviation: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec. Always in English, regardless of the sender's locale.
Year — Four digits. The original RFC 822 (from 1982) allowed two-digit years, which RFC 2822 deprecated. If you encounter a two-digit year in legacy data, RFC 2822 says: years 00–49 map to 2000–2049, years 50–99 map to 1950–1999.
Time — 24-hour clock, always with seconds. No AM/PM, no fractional seconds.
UTC offset — Required. Format is ±HHMM with no colon between hours and minutes. This is different from ISO 8601, which uses ±HH:MM (with a colon). The offset -0400 means "four hours behind UTC" (Eastern Daylight Time). The offset +0000 is UTC. The letter Z is not used — you must write +0000 for UTC.
Where You'll Encounter RFC 2822 Dates
Email headers. Every email has a Date: header in RFC 2822 format. Email clients parse this to show you when a message was sent. If you've ever exported emails from Gmail or Outlook and needed to work with the timestamps, you've dealt with this format.
RSS and Atom feeds. RSS 2.0 uses RFC 822/2822 dates in its <pubDate> elements. Atom feeds use ISO 8601 instead, which is one of several format differences between the two standards.
HTTP headers. HTTP uses a related but slightly different format (RFC 7231, derived from RFC 1123, which is itself a subset of RFC 2822). The HTTP date format looks like Sat, 29 Jun 2024 14:30:00 GMT — always in GMT, never with a numeric offset. You'll see this in Date, Last-Modified, Expires, and If-Modified-Since headers.
Log files and legacy systems. Some older Unix utilities and logging systems output dates in this format. The date -R command on Linux produces RFC 2822 output.
We added support for parsing named-month formats in the converter partly because of RFC 2822. When someone exports data from an email system or an RSS aggregator and needs to convert those dates to ISO 8601 for a database import, having a format that handles Jun 29, 2024 directly saves a step.
RFC 2822 vs. ISO 8601
| Feature | RFC 2822 | ISO 8601 |
|---|---|---|
| Primary use | Email, RSS, HTTP | APIs, databases, JSON, logging |
| Month format | Three-letter name (Jun) | Two-digit number (06) |
| Year position | After month | First |
| Day-of-week | Included (optional) | Not included |
| Timezone format | -0400 (no colon) | -04:00 (with colon) or Z |
| UTC indicator | +0000 | Z or +00:00 |
| Fractional seconds | Not supported | Supported |
| Date-only form | Not defined | YYYY-MM-DD |
| Sortable as string | No | Yes |
| Language-dependent | Yes (English month names) | No |
| Human readability | High | Medium |
The key practical difference: RFC 2822 dates are not lexicographically sortable. You can't sort them as strings and get chronological order, because the day-of-month comes before the year and months are abbreviated names. ISO 8601 dates sort correctly as plain strings because they use biggest-unit-first ordering with numeric values. This is why ISO 8601 won out for data storage and APIs.
Parsing and Generating RFC 2822 Dates
JavaScript
// JavaScript's Date can parse RFC 2822 (implementation-dependent but widely supported)
new Date("Sat, 29 Jun 2024 14:30:00 -0400")
// → Date object (usually works in all major browsers)
// Generate RFC 2822 format
const d = new Date("2024-06-29T18:30:00Z");
d.toUTCString();
// → "Sat, 29 Jun 2024 18:30:00 GMT" (close to RFC 2822, but uses GMT not offset)
// For exact RFC 2822 output, you need manual formatting or a library:
// Using Intl.DateTimeFormat for parts, then assembling manually
function toRFC2822(date, offsetMin) {
const days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
const months = ['Jan','Feb','Mar','Apr','May','Jun',
'Jul','Aug','Sep','Oct','Nov','Dec'];
const sign = offsetMin <= 0 ? '+' : '-';
const absOff = Math.abs(offsetMin);
const offH = String(Math.floor(absOff / 60)).padStart(2, '0');
const offM = String(absOff % 60).padStart(2, '0');
return `${days[date.getDay()]}, ${String(date.getDate()).padStart(2, '0')} ` +
`${months[date.getMonth()]} ${date.getFullYear()} ` +
`${String(date.getHours()).padStart(2, '0')}:` +
`${String(date.getMinutes()).padStart(2, '0')}:` +
`${String(date.getSeconds()).padStart(2, '0')} ${sign}${offH}${offM}`;
} Python
from email.utils import parsedate_to_datetime, format_datetime
from datetime import datetime, timezone, timedelta
# Parse RFC 2822
dt = parsedate_to_datetime("Sat, 29 Jun 2024 14:30:00 -0400")
# → datetime(2024, 6, 29, 14, 30, tzinfo=timezone(timedelta(hours=-4)))
# Generate RFC 2822
eastern = timezone(timedelta(hours=-4))
dt = datetime(2024, 6, 29, 14, 30, 0, tzinfo=eastern)
format_datetime(dt)
# → 'Sat, 29 Jun 2024 14:30:00 -0400'
# Note: Python's email.utils module is the correct tool for RFC 2822.
# Don't use strftime/strptime — the format is locale-dependent and
# won't produce compliant output in non-English locales. PHP
// PHP has built-in RFC 2822 support
$dt = new DateTime('2024-06-29T14:30:00-04:00');
echo $dt->format(DateTime::RFC2822);
// → "Sat, 29 Jun 2024 14:30:00 -0400"
// Parse RFC 2822
$dt = DateTime::createFromFormat(DateTime::RFC2822, 'Sat, 29 Jun 2024 14:30:00 -0400');
// PHP also has DATE_RFC2822 constant for date() function
echo date(DATE_RFC2822, 1719685800);
// → "Sat, 29 Jun 2024 14:30:00 -0400" Command Line
# Linux: generate RFC 2822 date
date -R
# → "Sat, 29 Jun 2024 14:30:00 -0400"
# macOS: no -R flag, use format string
date '+%a, %d %b %Y %H:%M:%S %z'
# → "Sat, 29 Jun 2024 14:30:00 -0400" Obsolete Forms You Might Encounter
RFC 2822 obsoleted RFC 822, which had some formats you'll still see in legacy data:
Named timezone abbreviations. RFC 822 allowed timezone abbreviations like EST, CST, PST instead of numeric offsets. RFC 2822 deprecated these because they're ambiguous (CST is used by both US Central time and China Standard Time). If you encounter them in old email headers, you'll need to resolve the ambiguity from context.
Two-digit years. 29 Jun 96 instead of 29 Jun 1996. RFC 2822's interpretation: 00–49 → 2000–2049, 50–99 → 1950–1999.
Extra whitespace and comments. RFC 822 allowed comments in parentheses within date strings: Sat, 29 Jun 2024 14:30:00 -0400 (EDT). The (EDT) is a comment. Robust parsers should handle this; naive regex parsers will choke on it.
Common Mistakes
Adding a colon to the offset. RFC 2822 uses -0400. ISO 8601 uses -04:00. Mixing them up produces invalid output that some parsers accept and others reject.
Using Z for UTC. RFC 2822 doesn't use Z. Use +0000 instead. Some parsers are lenient, but strict RFC 2822 validators will flag Z as invalid.
Non-English month names. RFC 2822 mandates English abbreviations. 29 Juin 2024 (French) or 29 Jun. 2024 (with a period) are not valid.
Wrong day-of-week. If the day-of-week is present, it must be correct. Mon, 29 Jun 2024 is invalid because June 29, 2024 is a Saturday. Most parsers ignore the day-of-week (they compute it from the date), but some validate it and reject the entire string if it's wrong.
Related Guides
For the format that's largely replaced RFC 2822 in modern APIs, see ISO 8601 Date Format Explained. If you're converting RFC 2822 dates from an email export, the converter's named-month formats can handle them directly — see How to Convert Dates in CSV Files for batch processing. For the full list of timezone abbreviations that RFC 822 allowed (and RFC 2822 deprecated), see the Timezone Abbreviations Reference.
Try It Yourself
Convert any date or timestamp instantly — free, no sign-up required.
Open the Converter