DevToolsmith

MongoDB ObjectId to Timestamp

Paste a MongoDB ObjectId to see when it was created, in UTC, your local time and Unix time. Or convert a date into an ObjectId to query documents by time range using the _id index.

Runs 100% in your browser — nothing is uploaded

Date → ObjectId (for range queries)

Build the smallest ObjectId for a given time, then query by _id to find documents created after (or before) it — no createdAt field or index needed.

ObjectId structure

An ObjectId is 12 bytes, usually shown as 24 hexadecimal characters:

507f1f77   bcf86cd799   439011
|--------| |----------| |------|
 timestamp   random       counter
 4 bytes     5 bytes      3 bytes
 (seconds)   (per process) (incrementing)

Because the timestamp comes first, ObjectIds sort roughly by creation time. That is why sorting by _id is a cheap way to get documents in insertion order.

Get the timestamp in code

MongoDB Shell (mongosh)

// mongosh
ObjectId("507f1f77bcf86cd799439011").getTimestamp()
// ISODate("2012-10-17T21:13:27.000Z")

// Documents created since a date, without a createdAt field
const since = ObjectId.createFromTime(new Date("2026-01-01") / 1000);
db.orders.find({ _id: { $gte: since } });

Node.js driver

import { ObjectId } from 'mongodb';

new ObjectId('507f1f77bcf86cd799439011').getTimestamp();
// 2012-10-17T21:13:27.000Z

ObjectId.createFromTime(Math.floor(Date.now() / 1000));

Python (PyMongo)

from bson import ObjectId
from datetime import datetime, timezone

ObjectId("507f1f77bcf86cd799439011").generation_time
# datetime.datetime(2012, 10, 17, 21, 13, 27, tzinfo=<bson.tz_util.FixedOffset ...>)

ObjectId.from_datetime(datetime(2026, 1, 1, tzinfo=timezone.utc))

Aggregation pipeline

db.users.aggregate([
  { $project: { createdAt: { $toDate: "$_id" } } }
])

Caveats

  • The timestamp reflects when the ID was created, which is not always when the document was saved, for example if an app pre-generates IDs or imports old data with new IDs.
  • Precision is one second. Several documents created in the same second are ordered by the counter.
  • Custom _id values (strings, numbers, UUIDs) don't carry a timestamp. For time-sortable UUIDs, see UUID v7.

Frequently asked questions

Does a MongoDB ObjectId contain the creation date?

Yes. The first 4 bytes (8 hex characters) of every ObjectId are a Unix timestamp in seconds, recording when the ID was generated, which is usually when the document was inserted. Paste an ObjectId above to read it.

How do I query MongoDB documents by date using _id?

Build an ObjectId whose timestamp is your boundary date and whose other bytes are zero, then use it in a range query: { _id: { $gte: ObjectId("…") } }. The Date → ObjectId converter above builds it for you and shows the full query. It uses the default _id index, so it is fast.

How accurate is the timestamp?

It has 1-second precision and comes from the clock of the machine that generated the ID, usually your application server. The driver creates the ID, not the database. If you need millisecond precision or the server’s time, store a separate createdAt field.

What are the other 8 bytes of an ObjectId?

Since MongoDB 3.4: a 5-byte random value generated once per process, followed by a 3-byte counter that starts at a random value and increments for each new ObjectId. Older ObjectIds used a machine ID and process ID instead of the random value.

Can I get an ObjectId’s date in an aggregation pipeline?

Yes. Use { $toDate: "$_id" } (MongoDB 4.0+) to convert the _id to a Date, which you can then group or filter by.