Skip to content

Commit 7623426

Browse files
committed
Add try_to_rfc2822, deprecate to_rfc2822
1 parent 675b4a8 commit 7623426

File tree

5 files changed

+57
-23
lines changed

5 files changed

+57
-23
lines changed

bench/benches/chrono.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ fn bench_datetime_to_rfc2822(c: &mut Criterion) {
4646
.unwrap(),
4747
)
4848
.unwrap();
49-
c.bench_function("bench_datetime_to_rfc2822", |b| b.iter(|| black_box(dt).to_rfc2822()));
49+
c.bench_function("bench_datetime_to_rfc2822", |b| {
50+
b.iter(|| black_box(dt).try_to_rfc2822().unwrap())
51+
});
5052
}
5153

5254
fn bench_datetime_to_rfc3339(c: &mut Criterion) {

src/datetime/mod.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -523,15 +523,40 @@ impl<Tz: TimeZone> DateTime<Tz> {
523523
///
524524
/// # Panics
525525
///
526-
/// Panics if the date can not be represented in this format: the year may not be negative and
527-
/// can not have more than 4 digits.
526+
/// RFC 2822 is only defined on years 0 through 9999, and this method panics on dates outside
527+
/// of that range.
528528
#[cfg(feature = "alloc")]
529529
#[must_use]
530+
#[deprecated(
531+
since = "0.4.32",
532+
note = "Can panic on years outside of the range 0..=9999. Use `try_to_rfc2822()` instead."
533+
)]
530534
pub fn to_rfc2822(&self) -> String {
535+
self.try_to_rfc2822().expect("date outside of defined range for rfc2822")
536+
}
537+
538+
/// Returns an RFC 2822 date and time string such as `Tue, 1 Jul 2003 10:52:37 +0200`.
539+
///
540+
/// # Errors
541+
///
542+
/// RFC 2822 is only defined on years 0 through 9999, and this method returns an error on dates
543+
/// outside of that range.
544+
///
545+
/// # Example
546+
///
547+
/// ```rust
548+
/// # use chrono::{TimeZone, Utc};
549+
/// let dt = Utc.with_ymd_and_hms(2023, 6, 10, 9, 18, 25).unwrap();
550+
/// assert_eq!(dt.try_to_rfc2822(), Some("Sat, 10 Jun 2023 09:18:25 +0000".to_owned()));
551+
///
552+
/// let dt = Utc.with_ymd_and_hms(10_000, 1, 1, 0, 0, 0).unwrap();
553+
/// assert_eq!(dt.try_to_rfc2822(), None);
554+
/// ```
555+
#[cfg(feature = "alloc")]
556+
pub fn try_to_rfc2822(&self) -> Option<String> {
531557
let mut result = String::with_capacity(32);
532-
write_rfc2822(&mut result, self.overflowing_naive_local(), self.offset.fix())
533-
.expect("writing rfc2822 datetime to string should never fail");
534-
result
558+
write_rfc2822(&mut result, self.overflowing_naive_local(), self.offset.fix()).ok()?;
559+
Some(result)
535560
}
536561

537562
/// Returns an RFC 3339 and ISO 8601 date and time string such as `1996-12-19T16:39:57-08:00`.

src/datetime/tests.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -457,12 +457,12 @@ fn test_datetime_rfc2822() {
457457

458458
// timezone 0
459459
assert_eq!(
460-
Utc.with_ymd_and_hms(2015, 2, 18, 23, 16, 9).unwrap().to_rfc2822(),
461-
"Wed, 18 Feb 2015 23:16:09 +0000"
460+
Utc.with_ymd_and_hms(2015, 2, 18, 23, 16, 9).unwrap().try_to_rfc2822().as_deref(),
461+
Some("Wed, 18 Feb 2015 23:16:09 +0000")
462462
);
463463
assert_eq!(
464-
Utc.with_ymd_and_hms(2015, 2, 1, 23, 16, 9).unwrap().to_rfc2822(),
465-
"Sun, 1 Feb 2015 23:16:09 +0000"
464+
Utc.with_ymd_and_hms(2015, 2, 1, 23, 16, 9).unwrap().try_to_rfc2822().as_deref(),
465+
Some("Sun, 1 Feb 2015 23:16:09 +0000")
466466
);
467467
// timezone +05
468468
assert_eq!(
@@ -473,8 +473,9 @@ fn test_datetime_rfc2822() {
473473
.unwrap()
474474
)
475475
.unwrap()
476-
.to_rfc2822(),
477-
"Wed, 18 Feb 2015 23:16:09 +0500"
476+
.try_to_rfc2822()
477+
.as_deref(),
478+
Some("Wed, 18 Feb 2015 23:16:09 +0500")
478479
);
479480
assert_eq!(
480481
DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:59:60 +0500"),
@@ -508,8 +509,9 @@ fn test_datetime_rfc2822() {
508509
.unwrap()
509510
)
510511
.unwrap()
511-
.to_rfc2822(),
512-
"Wed, 18 Feb 2015 23:59:60 +0500"
512+
.try_to_rfc2822()
513+
.as_deref(),
514+
Some("Wed, 18 Feb 2015 23:59:60 +0500")
513515
);
514516

515517
assert_eq!(
@@ -521,8 +523,8 @@ fn test_datetime_rfc2822() {
521523
Ok(FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2015, 2, 18, 23, 16, 9).unwrap())
522524
);
523525
assert_eq!(
524-
ymdhms_micro(&edt, 2015, 2, 18, 23, 59, 59, 1_234_567).to_rfc2822(),
525-
"Wed, 18 Feb 2015 23:59:60 +0500"
526+
ymdhms_micro(&edt, 2015, 2, 18, 23, 59, 59, 1_234_567).try_to_rfc2822().as_deref(),
527+
Some("Wed, 18 Feb 2015 23:59:60 +0500")
526528
);
527529
assert_eq!(
528530
DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:59:58 +0500"),
@@ -1339,8 +1341,8 @@ fn test_min_max_getters() {
13391341
let beyond_max = offset_max.from_utc_datetime(&NaiveDateTime::MAX);
13401342

13411343
assert_eq!(format!("{:?}", beyond_min), "-262144-12-31T22:00:00-02:00");
1342-
// RFC 2822 doesn't support years with more than 4 digits.
1343-
// assert_eq!(beyond_min.to_rfc2822(), "");
1344+
#[cfg(feature = "alloc")]
1345+
assert_eq!(beyond_min.try_to_rfc2822(), None); // doesn't support years with more than 4 digits.
13441346
#[cfg(feature = "alloc")]
13451347
assert_eq!(beyond_min.to_rfc3339(), "-262144-12-31T22:00:00-02:00");
13461348
#[cfg(feature = "alloc")]
@@ -1364,8 +1366,8 @@ fn test_min_max_getters() {
13641366
assert_eq!(beyond_min.nanosecond(), 0);
13651367

13661368
assert_eq!(format!("{:?}", beyond_max), "+262143-01-01T01:59:59.999999999+02:00");
1367-
// RFC 2822 doesn't support years with more than 4 digits.
1368-
// assert_eq!(beyond_max.to_rfc2822(), "");
1369+
#[cfg(feature = "alloc")]
1370+
assert_eq!(beyond_max.try_to_rfc2822(), None); // doesn't support years with more than 4 digits.
13691371
#[cfg(feature = "alloc")]
13701372
assert_eq!(beyond_max.to_rfc3339(), "+262143-01-01T01:59:59.999999999+02:00");
13711373
#[cfg(feature = "alloc")]

src/format/formatting.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,8 +595,13 @@ pub(crate) fn write_rfc3339(
595595
.format(w, off)
596596
}
597597

598+
/// Write datetimes like `Tue, 1 Jul 2003 10:52:37 +0200`, same as `%a, %d %b %Y %H:%M:%S %z`
599+
///
600+
/// # Errors
601+
///
602+
/// RFC 2822 is only defined on years 0 through 9999, and this function returns an error on dates
603+
/// outside that range.
598604
#[cfg(feature = "alloc")]
599-
/// write datetimes like `Tue, 1 Jul 2003 10:52:37 +0200`, same as `%a, %d %b %Y %H:%M:%S %z`
600605
pub(crate) fn write_rfc2822(
601606
w: &mut impl Write,
602607
dt: NaiveDateTime,

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@
236236
//!
237237
//! assert_eq!(dt.format("%a %b %e %T %Y").to_string(), dt.format("%c").to_string());
238238
//! assert_eq!(dt.to_string(), "2014-11-28 12:00:09 UTC");
239-
//! assert_eq!(dt.to_rfc2822(), "Fri, 28 Nov 2014 12:00:09 +0000");
239+
//! assert_eq!(dt.try_to_rfc2822().unwrap(), "Fri, 28 Nov 2014 12:00:09 +0000");
240240
//! assert_eq!(dt.to_rfc3339(), "2014-11-28T12:00:09+00:00");
241241
//! assert_eq!(format!("{:?}", dt), "2014-11-28T12:00:09Z");
242242
//!
@@ -325,7 +325,7 @@
325325
//!
326326
//! // Construct a datetime from epoch:
327327
//! let dt: DateTime<Utc> = DateTime::from_timestamp(1_500_000_000, 0).unwrap();
328-
//! assert_eq!(dt.to_rfc2822(), "Fri, 14 Jul 2017 02:40:00 +0000");
328+
//! assert_eq!(dt.try_to_rfc2822(), Some("Fri, 14 Jul 2017 02:40:00 +0000".to_owned()));
329329
//!
330330
//! // Get epoch value from a datetime:
331331
//! let dt = DateTime::parse_from_rfc2822("Fri, 14 Jul 2017 02:40:00 +0000").unwrap();

0 commit comments

Comments
 (0)