Convert Chrono DateTime to BSON in Rust MongoDB 3.4.1
Fix 'expected DateTime, found DateTime' error converting chrono::DateTime to BSON DateTime in Rust with mongodb 3.4.1. Add bson crate with chrono-0_4, use from_chrono() or Into for rust chrono, rust mongodb serialization.
How to convert chrono::DateTime to MongoDB BSON DateTime in Rust using mongodb crate v3.4.1?
In earlier versions with bson 3.1.0 and chrono-0_4 feature enabled:
bson = { version = "3.1.0", features = ["chrono-0_4"] }
Direct conversion was possible (e.g., BsonDateTime::from_chrono(expiry)).
In mongodb 3.x, this throws a type mismatch error due to different bson versions:
mismatched types
expected DateTime, found DateTime
(two different versions of crate bson are being used)
Enabling chrono-0_4 on mongodb itself fails:
mongodb = { version = "3.4.1", features = ["chrono-0_4"] }
package xxx depends on mongodb with feature chrono-0_4 but mongodb does not have that feature.
What is the straightforward way to serialize or convert chrono::DateTime to BSON Date in mongodb 3.4.1?
Use the standalone bson crate (the same version as mongodb) with the chrono-0_4 feature and convert chrono::DateTime into bson::DateTime via bson::DateTime::from_chrono() or Into. For mongodb v3.4.1 add bson = { version = "3.4.1", features = ["chrono-0_4"] } to Cargo.toml so Cargo unifies the bson type; then insert the converted bson::DateTime (or bson::Bson::DateTime(...)) into documents. This removes the “expected DateTime, found DateTime” mismatch caused by two different bson crate versions.
Contents
- Why the type mismatch happens (rust mongodb chrono)
- Cargo.toml fix: add bson with chrono-0_4 (bson datetime rust)
- Conversion examples: DateTime::from_chrono, Into, and building BSON docs
- Serde: serializing chrono fields as MongoDB Date (chrono datetime bson)
- Troubleshooting: check dependency tree and duplicates
- Sources
- Conclusion
Why the type mismatch happens (rust mongodb chrono)
You hit mismatched types expected DateTime, found DateTime because Rust treats types from different crate versions as distinct. If your project pulls one bson version (the standalone crate with chrono-0_4) while the mongodb crate depends on another bson version, bson::DateTime from one copy is not the same type as bson::DateTime from the other copy. Simple, annoying, and very Rusty.
Why can’t you just enable chrono-0_4 on mongodb? Because that feature isn’t exposed on the mongodb crate itself—trying mongodb = { version = "3.4.1", features = ["chrono-0_4"] } fails. The right approach is to make sure the dependency graph has a single bson version that exposes the chrono integration so your chrono::DateTime can be converted cleanly. See the same diagnosis and discussion on StackOverflow and the bson-rust issue tracker for the exact error and fixes: https://stackoverflow.com/questions/55735974/how-do-i-serialize-chronodatetime-fields-as-isodate-when-using-the-rust-mongo and https://github.com/mongodb/bson-rust/issues/303.
Cargo.toml fix: add bson with chrono-0_4 and match versions (bson datetime rust)
The straightforward fix is to depend explicitly on the same bson version that mongodb uses and enable the chrono feature there. Example minimal Cargo.toml:
[dependencies]
mongodb = "3.4.1"
bson = { version = "3.4.1", features = ["chrono-0_4"] } # <- enable chrono support here
chrono = "0.4" # optional, if you use chrono types directly
serde = { version = "1.0", features = ["derive"] } # if you serialize/deserialize structs
By adding bson with version 3.4.1 Cargo will unify the bson crate in the dependency graph (so there’s only one bson::DateTime type). After this, conversions such as bson::DateTime::from_chrono() will use the same bson type as the mongodb client.
For reference on the bson::DateTime helpers and conversion functions see the docs: https://docs.rs/bson/latest/bson/struct.DateTime.html.
Conversion examples: DateTime::from_chrono, Into, and building BSON docs
A few concrete examples you can paste into an async function:
use chrono::Utc;
use bson::{DateTime as BsonDateTime, doc, Bson};
let expiry: chrono::DateTime<Utc> = Utc::now();
let bson_dt: BsonDateTime = BsonDateTime::from_chrono(expiry);
// Or via Into:
let bson_dt2: BsonDateTime = expiry.into();
// Build a document
let doc = doc! { "expires_at": Bson::DateTime(bson_dt) };
// Insert with mongodb
let coll = client.database("mydb").collection("items");
coll.insert_one(doc, None).await?;
Notes and small gotchas:
bson::DateTimetruncates to milliseconds to match the MongoDB spec (see docs).bson::doc!often acceptsbson::DateTimedirectly, but wrapping asBson::DateTime(...)is explicit and clear.- After you unify the
bsonversion in Cargo.toml,BsonDateTime::from_chrono(...)andexpiry.into()will compile without the type mismatch.
Serde: serializing chrono::DateTime fields as MongoDB Date (chrono datetime bson)
If you prefer typed structs with Serde, use the provided serde helper so serde encodes chrono::DateTime as BSON Date:
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Authorization {
#[serde(with = "bson::serde_helpers::chrono_datetime_as_bson_datetime")]
start_date: Option<DateTime<Utc>>,
#[serde(with = "bson::serde_helpers::chrono_datetime_as_bson_datetime")]
end_date: Option<DateTime<Utc>>,
name: String,
}
That helper handles Option<DateTime<Utc>> fields as well (it works directly for optional fields). There’s also an alternative using serde_with::serde_as if you prefer that style; see the bson DateTime docs for examples: https://docs.rs/bson/latest/bson/struct.DateTime.html. The GitHub issue thread also includes examples and discussion about using the helpers: https://github.com/mongodb/bson-rust/issues/303.
Troubleshooting: check dependency tree and duplicates
If you still see the mismatch after updating Cargo.toml, inspect your dependency graph:
- Run
cargo tree | grep bsonorcargo tree -dto find duplicatebsonentries. - If another crate pins a different
bsonversion, try to align versions (update that crate or add an explicitbson = { version = "3.4.1", features = ["chrono-0_4"] }dependency so Cargo resolves to a single version). - You can also run
cargo update -p bson --precise 3.4.1to nudge Cargo toward a single version, but use that carefully—pinning can hide deeper compatibility issues.
If everything is unified and you still get errors, re-run cargo clean and build again. The underlying problem is always duplicate versions of the same crate; once the graph has a single bson crate the conversions work.
Sources
- StackOverflow — How do I serialize chrono::DateTime fields as ISODate when using the Rust Mongo driver prototype?
- GitHub — Can’t serialize/deserialize struct which contains Option<chrono::DateTime
> field. · Issue #303 · mongodb/bson-rust - DateTime in bson - Rust (docs.rs)
- bson - crates.io: Rust Package Registry
- GitHub - mongodb/bson-rust: Encoding and decoding support for BSON in Rust
- Mastering DateTime in Rust: Converting Strings to BSON Dates for MongoDB — Medium
Conclusion
In short: align your bson dependency with mongodb and enable chrono-0_4 on that bson crate, then convert with bson::DateTime::from_chrono() (or Into). That single change (add bson = { version = "3.4.1", features = ["chrono-0_4"] }) fixes the “expected DateTime, found DateTime” error for rust mongodb chrono and gives you clean bson datetime rust serialization.