MongoDB ObjectId ↔ timestamp converter
Extract the creation date hidden in any MongoDB ObjectId, or generate
min/max ObjectIds from a date to run _id range queries — no
driver, no shell, all in your browser.
epoch timestamp shortcuts
ObjectId → timestamp
date / timestamp → ObjectId
Only the first 4 bytes of an ObjectId encode time (seconds, UTC).
Use min as an inclusive lower bound and max as an inclusive upper bound
for _id range queries.
MongoDB _id range queries
How does an ObjectId encode time?
A MongoDB ObjectId is a 12-byte identifier, written as 24 hex
characters, and only its first 4 bytes encode time: a big-endian count of
seconds since the Unix epoch (00:00:00 UTC, 1 January 1970).
The remaining 8 bytes are a random per-process value and an incrementing
counter, which keep ObjectIds created in the same second unique — such
ObjectIds share their first 8 hex characters but differ in the rest.
Precision is one second; milliseconds are not stored. The timestamp
records when the ObjectId was generated, usually the moment the document
was inserted — MongoDB drivers generate ObjectIds client-side by default,
so the encoded time comes from the client's clock, not the server's.
Because the timestamp sits in the most significant bytes, ObjectIds sort
roughly by creation time: one created in a later second always compares
greater, but within the same second the order follows the random value
and counter, not the exact moment — and ObjectIds from clients with
skewed clocks can sort out of order. Second-level ordering is all that
date-based _id range queries need, so they work without a
separate createdAt field.
Querying _id by date
Because ObjectIds compare by their timestamp prefix first, you can filter a
collection by creation date without a separate createdAt
field. Generate the min ObjectId (timestamp + 16 zeros) for the
start of your range and the max ObjectId (timestamp + 16
fs) for the end, then query
{ _id: { $gte: ObjectId("<min>"), $lte: ObjectId("<max>") } }.
Min is an inclusive lower bound and max an inclusive upper bound. The
range queries card above writes these filters for you — last 15 minutes,
today, yesterday, older than 30 days or any custom window — for mongosh,
the Node.js driver and PyMongo.