From df5c5f122ade03d2a0af3642685efe3cc7fe7698 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Sat, 10 Jun 2023 10:26:01 +0200 Subject: [PATCH] Never return an error when formatting the `RFC2822` item. --- src/datetime/mod.rs | 6 +++++- src/format/formatting.rs | 22 ++++++++-------------- src/format/mod.rs | 4 ++++ 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index 91b51787ae..a65f485e31 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -554,8 +554,12 @@ impl DateTime { /// ``` #[cfg(feature = "alloc")] pub fn try_to_rfc2822(&self) -> Option { + let naive_local = self.overflowing_naive_local(); + if !(0..=9999).contains(&naive_local.year()) { + return None; + } let mut result = String::with_capacity(32); - write_rfc2822(&mut result, self.overflowing_naive_local(), self.offset.fix()).ok()?; + write_rfc2822(&mut result, naive_local, self.offset.fix()).ok()?; Some(result) } diff --git a/src/format/formatting.rs b/src/format/formatting.rs index f80e1dc2de..3f9b588312 100644 --- a/src/format/formatting.rs +++ b/src/format/formatting.rs @@ -599,24 +599,13 @@ pub(crate) fn write_rfc3339( .format(w, off) } -/// Write datetimes like `Tue, 1 Jul 2003 10:52:37 +0200`, same as `%a, %d %b %Y %H:%M:%S %z` -/// -/// # Errors -/// -/// RFC 2822 is only defined on years 0 through 9999, and this function returns an error on dates -/// outside that range. +/// Write datetimes like `Tue, 1 Jul 2003 10:52:37 +0200`, similar to `%a, %d %b %Y %H:%M:%S %z`. #[cfg(feature = "alloc")] pub(crate) fn write_rfc2822( w: &mut impl Write, dt: NaiveDateTime, off: FixedOffset, ) -> fmt::Result { - let year = dt.year(); - // RFC2822 is only defined on years 0 through 9999 - if !(0..=9999).contains(&year) { - return Err(fmt::Error); - } - let english = default_locale(); w.write_str(short_weekdays(english)[dt.weekday().num_days_from_sunday() as usize])?; @@ -630,8 +619,13 @@ pub(crate) fn write_rfc2822( w.write_char(' ')?; w.write_str(short_months(english)[dt.month0() as usize])?; w.write_char(' ')?; - write_hundreds(w, (year / 100) as u8)?; - write_hundreds(w, (year % 100) as u8)?; + let year = dt.year(); + if (0..=9999).contains(&year) { + write_hundreds(w, (year / 100) as u8)?; + write_hundreds(w, (year % 100) as u8)?; + } else { + write!(w, "{:04}", year)?; + } w.write_char(' ')?; let (hour, min, sec) = dt.time().hms(); diff --git a/src/format/mod.rs b/src/format/mod.rs index cc8e2938e0..0e44a4ea53 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -240,6 +240,10 @@ pub enum Fixed { /// Parsing allows an optional colon. TimezoneOffsetZ, /// RFC 2822 date and time syntax. Commonly used for email and MIME date and time. + /// + /// This does not always output a strictly valid RFC 2822 string. RFC 2822 is only defined on + /// years 0 through 9999. We format a date outside these ranges anyway to prevent a panic when + /// formatting. RFC2822, /// RFC 3339 & ISO 8601 date and time syntax. ///