$dayOfMonth is a MongoDB aggregation expression that returns the day of the month as an integer from 1 to 31. Default timezone is UTC; you can pass a timezone when local day matters.
Remember
$dayOfMonth = calendar day number (1–31)
{ $dayOfMonth: <dateExpression> }
// or with timezone:
{ $dayOfMonth: { date: <date>, timezone: <string> } }
input → Date / Timestamp / ObjectId (not a string)
output → integer 1 … 31
default zone → UTC
null / missing → null
string date → error (parse with $dateFromString first)
For local day, use { $dayOfMonth: { date: "$starts_at", timezone: "America/New_York" } }.
Optionally filter with $match + $expr on that day number.
Piece
Required?
Role
Date expression
Yes
Date / Timestamp / ObjectId to read
timezone
No
Local day instead of UTC
Result
—
Integer 1–31
Pseudocode
Pseudocode
for each document:
d = evaluate(dateExpression)
if d is null or missing:
result = null
else:
result = day-of-month of d in timezone (default UTC)
// integer from 1 to 31
emit { ..., field: result }
Reference
Cheat Sheet
Keep these facts handy while extracting day-of-month values.
Watch $dayOfMonth return the calendar day number (UTC) for a few dates.
Simulates $dayOfMonth in UTC (same idea as the mongosh examples below).
Result
date = ISODate("2026-10-02T09:15:00.000Z")
$dayOfMonth → 2
{ day: 2 }
Trace
Worked Walkthrough — Day 2
An event starts on 2026-10-02T09:15:00Z. We want the day number from that Date.
Calculation
Document:
{ starts_at: ISODate("2026-10-02T09:15:00.000Z") }
$dayOfMonth: "$starts_at"
Step by step (UTC):
year → 2026
month → 10 (October)
day → 2
Result:
2
Check: October 2 → day-of-month is 2 ✓
Code
MongoDB Examples
We use one event with a start time. First we store it, then we extract the day number, then we filter for events that start on that day of the 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.
Same stored document. Still using starts_at from Example 1.
Compare inside $expr. Aggregation operators like $dayOfMonth need $expr inside $match.
Keep matches only. Day equals 2, so Launch stays in the result.
Project a clean shape. Output shows title and the day number.
Edge Cases & Pitfalls
Check these before using $dayOfMonth in production pipelines.
type
Strings are not allowed
Pass a Date, not "2026-10-02". Parse text first with $dateFromString.
tz
Default day is UTC
Near midnight, local day can differ from UTC. Use the document form with timezone when local calendars matter.
name
Not the same as $dayOfWeek
$dayOfMonth is 1–31 on the calendar. $dayOfWeek is weekday (Sunday–Saturday numbering).
null
Null date becomes null
Missing or null dates return null, not an error. Handle them before grouping or filtering if needed.
Analysis
Performance Notes
Approach
Cost
Best for
$dayOfMonth alone
Per-document extract
Reports and computed fields
$match + $expr
Scan + expression
Filtering by day number
Store day ahead of time
Write cost, cheaper filters
Very frequent day-based queries
Extracting a day number is cheap compared with large sorts or joins. Filter early with $match when only some documents need the day field.
Remember
Key Takeaways
Role: Date → day of month integer (1–31).
Default zone: UTC (optional timezone available).
Input: Date only—not a date string.
Filter tip: use $match + $expr with $eq.
One line:$dayOfMonth answers “which day of the month is this Date?”—as a number from 1 to 31.
Frequently Asked Questions
$dayOfMonth returns an integer from 1 to 31 for the day of the month of a BSON Date. For example, 2026-10-02 returns 2. Use it inside aggregation stages such as $project and $addFields.
Short form: { $dayOfMonth: <dateExpression> }. With timezone: { $dayOfMonth: { date: <dateExpression>, timezone: <string> } }. Without timezone, the day is in UTC.
Default is UTC. Pass timezone (Olson ID or UTC offset) when you need the day as it appears in a local zone—especially near midnight.
$dayOfMonth returns one integer (the day). $dateToParts returns a full document with year, month, day, hour, and more.
No. It needs a Date, Timestamp, or ObjectId. Parse text first with $dateFromString.
Yes in spirit for the UTC case. Think of $dayOfMonth as MongoDB’s aggregation version of reading the calendar day—run it in the pipeline, not as a standalone find() filter.