MongoDB $dateTrunc Operator

Beginner
5 min read
Updated: Oct 2026
3 examples
Live preview

What Is $dateTrunc?

$dateTrunc is a MongoDB aggregation expression that rounds a Date down to the start of a time period—day, month, hour, and more. Use it to bucket events for daily or monthly reports (MongoDB 5.0+).

Remember
$dateTrunc = snap Date to period start

{ $dateTrunc: {
    date:        <date>,     // required
    unit:        <string>,   // required  e.g. "day"
    binSize:     <number>,   // optional  default 1
    timezone:    <string>,   // optional  default UTC
    startOfWeek: <string>    // optional  for unit "week"
  }
}

units → year, quarter, week, month, day,
        hour, minute, second

returns → a new Date at the boundary
example → 09:15 truncated to day → 00:00 same day
UsePrefer
Bucket dates for grouping$dateTrunc
Split into year/month/day numbers$dateToParts
Format a Date as text$dateToString

How to Use $dateTrunc in MongoDB

Pick the Date field and the unit you want to snap to, then use the result as a group key.

  1. Choose an expression stage ($addFields or $project).
  2. Set date to a Date field (or Date expression).
  3. Set unit (for example "day" or "month").
  4. Optionally set binSize, timezone, or startOfWeek (for weeks).
PieceRequired?Role
dateYesDate / Timestamp / ObjectId to truncate
unitYesPeriod boundary ("day", "month", …)
binSizeNoBucket width in units (default 1)
timezone / startOfWeekNoLocal calendar / week start day

Pseudocode

Pseudocode
for each document:
    d = evaluate(date)
    u = evaluate(unit)
    if d is null or missing:
        result = null
    else:
        result = start of the period containing d
                // e.g. unit "day" → midnight of that day
    emit { ..., field: result }

Cheat Sheet

Keep these facts handy while truncating dates for buckets.

TopicDetail
TypeAggregation expression (MongoDB 5.0+)
Syntax{ $dateTrunc: { date: "$starts_at", unit: "day" } }
ReturnsA new BSON Date at the period start
Day bucketunit: "day" → midnight of that day (UTC by default)
Month bucketunit: "month" → first day of that month
binSizeunit: "hour", binSize: 2 → every 2 hours
Sample check2026-10-02 09:15 → day trunc → 2026-10-02 00:00

Live Preview

Watch $dateTrunc snap a timestamp down to day, hour, or month (UTC).

Simulates $dateTrunc for ISODate("2026-10-02T09:15:00.000Z").

Result
date = ISODate("2026-10-02T09:15:00.000Z")
unit = "day"

$dateTrunc → ISODate("2026-10-02T00:00:00.000Z")

{ day_bucket: ISODate("2026-10-02T00:00:00.000Z") }

Worked Walkthrough — Truncate to Day

An event starts at 2026-10-02T09:15:00Z. For a daily report we want midnight of that same day.

Calculation
Document:
  { starts_at: ISODate("2026-10-02T09:15:00.000Z") }

$dateTrunc: {
  date: "$starts_at",
  unit: "day"
}

Step by step (UTC):
  1) Read 2026-10-02 09:15
  2) Keep the calendar day
  3) Clear time → 00:00:00.000

Result:
  ISODate("2026-10-02T00:00:00.000Z")

All events that day share this bucket key.

MongoDB Examples

We use one event with a start time. First we store it, then we truncate to day, then to month. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine one event named Launch that starts at 2026-10-02 09:15 UTC. We save that Date in a collection named events.

mongosh
db.events.insertOne({
  _id: 1,
  title: "Launch",
  starts_at: ISODate("2026-10-02T09:15:00.000Z")
});

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps one document in events. Run find() to see it:

mongosh
db.events.find()

Read that document like this:

Field in MongoDBValuePlain English
_id1Document id (row number for this lesson)
title"Launch"Event name
starts_atISODate("2026-10-02T09:15:00.000Z")Exact start time
Picture
Exact time:

  2026-10-02 09:15:00 UTC
         |
         v  $dateTrunc unit:"day"
  2026-10-02 00:00:00 UTC   ← day bucket

         |
         v  $dateTrunc unit:"month"
  2026-10-01 00:00:00 UTC   ← month bucket

How It Works

  1. Insert once. insertOne adds a single event document to events.
  2. Store a real Date. ISODate(...) creates a BSON Date, not a string.
  3. find() shows the same shape. What you inserted is what you get back—ready for $dateTrunc next.

Example 2 — Truncate to Day

Goal: snap starts_at to midnight of the same UTC day for daily grouping.

mongosh
db.events.aggregate([
  {
    $addFields: {
      day_bucket: {
        $dateTrunc: {
          date: "$starts_at",
          unit: "day"
        }
      }
    }
  }
]);

How It Works

  1. Read the stored Date. MongoDB already has starts_at from Example 1.
  2. Choose unit "day". Everything smaller than a day is cleared.
  3. Get midnight UTC. 09:15 becomes 00:00 on 2026-10-02.
  4. Keep all fields. $addFields adds day_bucket next to starts_at—nothing is deleted.

Example 3 — Truncate to Month

Same Date, but snap to the first day of the month for monthly rollups.

mongosh
db.events.aggregate([
  {
    $addFields: {
      month_bucket: {
        $dateTrunc: {
          date: "$starts_at",
          unit: "month"
        }
      }
    }
  }
]);

How It Works

  1. Same stored document. Still using starts_at from Example 1.
  2. Change the unit. "month" instead of "day".
  3. Land on month start. October 2 becomes October 1 at 00:00:00.000Z.
  4. Easy check. All October events share the same month bucket key.

Edge Cases & Pitfalls

Check these before using $dateTrunc in production pipelines.

type

Input must be a Date

String dates need $dateFromString first. $dateTrunc does not parse text.

tz

Default buckets are UTC

A late evening in New York can fall on the next UTC day. Set timezone when daily buckets must match a local calendar.

week

Week start defaults to Sunday

For Monday-based weeks, set startOfWeek: "Monday" when unit is "week".

null

Null date becomes null

Missing or null dates return null, not an error. Filter them before grouping if null buckets are unwanted.

Performance Notes

ApproachCostBest for
$dateTrunc alonePer-document date mathDaily / monthly group keys
+ $group on the bucketO(docs) + groupingRollups and time-series summaries
+ timezoneSlightly heavierLocal-day reporting near DST

Truncation is cheap compared with large sorts or joins. Filter early with $match when only some documents need a bucket.

Key Takeaways

  • Role: snap a Date down to a period start.
  • Inputs: date + unit (optional binSize).
  • Returns: a Date (great as a $group key).
  • Pattern: unit: "day" for daily buckets.

One line: $dateTrunc answers “what is the start of this day/month/hour for my Date?”

Frequently Asked Questions

$dateTrunc rounds a BSON Date down to the start of a time period—such as the beginning of the day, hour, or month. Use it for daily rollups, time-series bucketing, and grouping events by calendar periods (MongoDB 5.0+).
Use { $dateTrunc: { date: <date>, unit: <string>, binSize: <number>, timezone: <string>, startOfWeek: <string> } }. date and unit are required. binSize defaults to 1.
year, quarter, week, month, day, hour, minute, and second. Pass the unit as a string such as "day" or "month".
$dateTrunc returns a BSON Date at a period boundary. $dateToParts returns a document of numeric components. Use $dateTrunc when you need a Date for grouping; use $dateToParts when you need separate integers.
binSize sets how many units make one bucket. For example, unit "hour" and binSize 2 truncates to every 2-hour boundary. It defaults to 1.
No. It computes a new Date in the pipeline result. Your original field stays unchanged unless you write the result back with an update.

Next: $dayOfMonth

Extract the day of the month (1–31) from a BSON Date.

$dayOfMonth tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful