@@ -1213,6 +1213,92 @@ pub mod ts_seconds_option {
12131213 }
12141214}
12151215
1216+ /// Ser/de to/from RFC 2822 strings
1217+ ///
1218+ /// Intended for use with `serde`'s `with` attribute.
1219+ ///
1220+ /// # Example:
1221+ ///
1222+ /// ```rust
1223+ /// use chrono::{DateTime, NaiveDate, FixedOffset, TimeZone};
1224+ /// use serde_derive::{Deserialize, Serialize};
1225+ ///
1226+ /// #[derive(Deserialize, Serialize)]
1227+ /// struct Example {
1228+ /// #[serde(with = "chrono::serde::rfc2822")]
1229+ /// time: DateTime<FixedOffset>
1230+ /// }
1231+ /// let offset = 3600;
1232+ /// let actual_time = NaiveDate::from_ymd_opt(2018, 5, 17).unwrap()
1233+ /// .and_hms_opt(02, 04, 59).unwrap()
1234+ /// .and_local_timezone(TimeZone::from_offset(&FixedOffset::east_opt(offset).unwrap())).unwrap();
1235+ /// let to_serialize = Example {
1236+ /// time: actual_time.clone(),
1237+ /// };
1238+ ///
1239+ /// let serialized = serde_json::to_string(&to_serialize).unwrap();
1240+ /// assert_eq!(serialized, r#"{"time":"Thu, 17 May 2018 02:04:59 +0100"}"#);
1241+ ///
1242+ /// let deserialized: Example = serde_json::from_str(&serialized).unwrap();
1243+ /// assert_eq!(deserialized.time, actual_time);
1244+ /// ```
1245+ pub mod rfc2822 {
1246+ use crate :: { DateTime , FixedOffset , Offset , TimeZone } ;
1247+ use crate :: format:: write_rfc2822;
1248+ use core:: fmt;
1249+ use serde:: { de, ser} ;
1250+
1251+ /// Serialize a datetime into an RFC 2822 formatted string, e.g. "01 Jun 2016 14:31:46 -0700"
1252+ ///
1253+ /// Intended for use with `serde`s `serialize_with` attribute.
1254+ pub fn serialize < S > ( dt : & DateTime < FixedOffset > , serializer : S ) -> Result < S :: Ok , S :: Error >
1255+ where
1256+ S : ser:: Serializer ,
1257+ {
1258+ struct FormatRfc2822 < ' a , Tz : TimeZone > {
1259+ inner : & ' a DateTime < Tz > ,
1260+ }
1261+
1262+ impl < ' a , Tz : TimeZone > fmt:: Display for FormatRfc2822 < ' a , Tz > {
1263+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1264+ let naive = self . inner . naive_local ( ) ;
1265+ let offset = self . inner . offset . fix ( ) ;
1266+ write_rfc2822 ( f, naive, offset)
1267+ }
1268+ }
1269+
1270+ serializer. collect_str ( & FormatRfc2822 { inner : dt } )
1271+ }
1272+
1273+ #[ derive( Debug ) ]
1274+ struct Rfc2822Visitor ;
1275+
1276+ /// Deserialize a [`DateTime`] from an RFC 2822 datetime
1277+ ///
1278+ /// Intended for use with `serde`s `deserialize_with` attribute.
1279+ pub fn deserialize < ' de , D > ( deserializer : D ) -> Result < DateTime < FixedOffset > , D :: Error >
1280+ where
1281+ D : de:: Deserializer < ' de > ,
1282+ {
1283+ deserializer. deserialize_str ( Rfc2822Visitor )
1284+ }
1285+
1286+ impl < ' de > de:: Visitor < ' de > for Rfc2822Visitor {
1287+ type Value = DateTime < FixedOffset > ;
1288+
1289+ fn expecting ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
1290+ formatter. write_str ( "an RFC 2822 formatted datetime string" )
1291+ }
1292+
1293+ fn visit_str < E > ( self , date_string : & str ) -> Result < Self :: Value , E >
1294+ where
1295+ E : de:: Error ,
1296+ {
1297+ DateTime :: parse_from_rfc2822 ( date_string) . map_err ( E :: custom)
1298+ }
1299+ }
1300+ }
1301+
12161302#[ cfg( test) ]
12171303mod tests {
12181304 #[ cfg( feature = "clock" ) ]
0 commit comments