@@ -5,6 +5,11 @@ use std::{
55 time:: { Duration , SystemTime } ,
66} ;
77
8+ #[ cfg( all( feature = "serde_with" , feature = "chrono-0_4" ) ) ]
9+ use serde:: { Deserialize , Deserializer , Serialize } ;
10+ #[ cfg( all( feature = "serde_with" , feature = "chrono-0_4" ) ) ]
11+ use serde_with:: { DeserializeAs , SerializeAs } ;
12+
813use chrono:: { LocalResult , TimeZone , Utc } ;
914
1015/// Struct representing a BSON datetime.
@@ -54,6 +59,40 @@ use chrono::{LocalResult, TimeZone, Utc};
5459/// }
5560/// # }
5661/// ```
62+ /// ## The `serde_with` feature flag
63+ ///
64+ /// The `serde_with` feature can be enabled to support more ergonomic serde attributes for
65+ /// (de)serializing `chrono::DateTime` from/to BSON via the [`serde_with`](https://docs.rs/serde_with/1.11.0/serde_with/)
66+ /// crate. The main benefit of this compared to the regular `serde_helpers` is that `serde_with` can
67+ /// handle nested `chrono::DateTime` values (e.g. in `Option`), whereas the former only works on
68+ /// fields that are exactly `chrono::DateTime`.
69+ /// ```
70+ /// # #[cfg(all(feature = "chrono-0_4", feature = "serde_with"))]
71+ /// # {
72+ /// use serde::{Deserialize, Serialize};
73+ /// use bson::doc;
74+ ///
75+ /// #[serde_with::serde_as]
76+ /// #[derive(Deserialize, Serialize, PartialEq, Debug)]
77+ /// struct Foo {
78+ /// /// Serializes as a BSON datetime rather than using `chrono::DateTime`'s serialization
79+ /// #[serde_as(as = "Option<bson::DateTime>")]
80+ /// as_bson: Option<chrono::DateTime<chrono::Utc>>,
81+ /// }
82+ ///
83+ /// let dt = chrono::Utc::now();
84+ /// let foo = Foo {
85+ /// as_bson: Some(dt),
86+ /// };
87+ ///
88+ /// let expected = doc! {
89+ /// "as_bson": bson::DateTime::from_chrono(dt),
90+ /// };
91+ ///
92+ /// assert_eq!(bson::to_document(&foo)?, expected);
93+ /// # }
94+ /// # Ok::<(), Box<dyn std::error::Error>>(())
95+ /// ```
5796#[ derive( Eq , PartialEq , Ord , PartialOrd , Hash , Copy , Clone ) ]
5897pub struct DateTime ( i64 ) ;
5998
@@ -234,6 +273,33 @@ impl<T: chrono::TimeZone> From<chrono::DateTime<T>> for crate::DateTime {
234273 }
235274}
236275
276+ #[ cfg( all( feature = "chrono-0_4" , feature = "serde_with" ) ) ]
277+ #[ cfg_attr( docsrs, doc( cfg( all( feature = "chrono-0_4" , feature = "serde_with" ) ) ) ) ]
278+ impl < ' de > DeserializeAs < ' de , chrono:: DateTime < Utc > > for crate :: DateTime {
279+ fn deserialize_as < D > ( deserializer : D ) -> std:: result:: Result < chrono:: DateTime < Utc > , D :: Error >
280+ where
281+ D : Deserializer < ' de > ,
282+ {
283+ let dt = DateTime :: deserialize ( deserializer) ?;
284+ Ok ( dt. to_chrono ( ) )
285+ }
286+ }
287+
288+ #[ cfg( all( feature = "chrono-0_4" , feature = "serde_with" ) ) ]
289+ #[ cfg_attr( docsrs, doc( cfg( all( feature = "chrono-0_4" , feature = "chrono-0_4" ) ) ) ) ]
290+ impl SerializeAs < chrono:: DateTime < Utc > > for crate :: DateTime {
291+ fn serialize_as < S > (
292+ source : & chrono:: DateTime < Utc > ,
293+ serializer : S ,
294+ ) -> std:: result:: Result < S :: Ok , S :: Error >
295+ where
296+ S : serde:: Serializer ,
297+ {
298+ let dt = DateTime :: from_chrono ( * source) ;
299+ dt. serialize ( serializer)
300+ }
301+ }
302+
237303/// Errors that can occur during [`DateTime`] construction and generation.
238304#[ derive( Clone , Debug ) ]
239305#[ non_exhaustive]
0 commit comments