getDate()
ES1+Returns the day of the month, from 1 to 31, for the given date according to local time. Unlike getMonth(), this getter is one-based, matching how humans write dates. Paired with setDate(), it is also the standard tool for safe day-based date arithmetic.
Syntax
date.getDate()Return Value
A number (1-31) representing the day of the month
Examples
const date = new Date('2024-03-15');
console.log(date.getDate()); 📌 When to Use
Use getDate() when you need the day-of-month component: rendering the number in a calendar cell, checking whether today is the 1st for a monthly job, computing billing anchors, formatting dates by hand, or driving "day N of the month" business rules. Its most valuable use is arithmetic in combination with setDate(): date.setDate(date.getDate() + 7) adds a week and lets the engine handle month lengths, leap years, and year boundaries. Crucially, because setDate() works through the local calendar, this idiom also survives daylight saving transitions, whereas adding 7 * 86400000 milliseconds to a timestamp lands an hour off twice a year in DST-observing time zones. The related trick new Date(year, month + 1, 0).getDate() returns the number of days in a month, which underlies calendar grids and billing-day clamping. Keep in mind the distinction from getDay(), which returns the weekday index, and the local-time semantics: for storage keys or server logic use getUTCDate(). If your value is conceptually a calendar day with no time attached, such as a due date, Temporal.PlainDate expresses that intent more safely than a Date pinned to midnight.
⚠️ Common Mistakes
Confusing getDate() with getDay(). getDate() is the day of the month (1-31); getDay() is the day of the week (0-6). The names are terrible and the bug is common; code that renders a calendar with getDay() where getDate() belongs shows numbers 0-6 in every cell.
Adding days by adding 86,400,000 milliseconds per day to getTime(). Across a daylight saving transition a local day is 23 or 25 hours, so the result drifts an hour and, when later truncated to a date, can land on the wrong day. date.setDate(date.getDate() + n) is DST-safe because it goes through the calendar.
Assuming every month has the day you are constructing. Building "the 31st of next month" or even "the 29th of February" rolls over into the following month silently: new Date(2025, 1, 30) is March 2. Billing and subscription code must clamp to the month's last day explicitly.
The UTC parsing trap: new Date("2024-03-10").getDate() returns 9 for users in the Americas, because date-only ISO strings parse as UTC midnight while getDate() reads local time. This is the single most reported "JavaScript shows the wrong date" bug.
Comparing calendar days by comparing full timestamps. Two Dates on the same local day rarely have equal getTime() values; same-day checks must compare getFullYear(), getMonth(), and getDate() together (or compare formatted date-only strings), not the raw instants.
✅ Best Practices
Do all day arithmetic through the calendar: date.setDate(date.getDate() + n) on a clone. It normalizes month ends, leap years, year boundaries, and DST for free, which manual millisecond math does not.
Get a month's length with new Date(year, month + 1, 0).getDate(); day 0 means "last day of the previous month". Use it to clamp billing days and to size calendar grids.
Compare calendar days, not instants: write an isSameLocalDay(a, b) helper that compares year, month, and date fields, and use it for "today" highlighting, deduplication, and streak logic.
Zero-pad when building sortable keys: String(date.getDate()).padStart(2, "0"), combined with padded month, keeps string keys lexicographically ordered; for user display, let Intl.DateTimeFormat choose the correct form instead.
For due dates, birthdays, and other timeless calendar days, prefer Temporal.PlainDate (or a library like date-fns) in new code; PlainDate.add({ days: n }) and until() express day arithmetic without midnight-and-timezone pitfalls.
⚡ Performance Notes
getDate() reads a field from the Date's cached local-time breakdown, so its cost is negligible and constant; the engine performs the timestamp-to-local conversion once per instance and shares it across getters. setDate() re-normalizes the internal timestamp but is still O(1) and cheap, far cheaper than allocating replacement Date objects in a loop. The patterns to watch are structural: looping day-by-day across large ranges with a new Date per step allocates garbage proportional to the range, so reuse one mutable cursor Date inside tight loops and clone only what you keep. In the business-day example here, the while loop advances one calendar day at a time, which is clear and fast for realistic spans; for spans of thousands of days, compute whole weeks arithmetically first and loop only the remainder.
🌍 Real World Example
Subscription Billing Date Calculator
Subscription billing is where day-of-month edge cases bite hardest: a customer who signs up on the 31st still expects a charge every month, including 28-day February. This example finds the next billing date by moving to the following month when needed and then clamping the anchor day to the target month's actual length using the day-zero trick. The days-until countdown uses timestamp subtraction, appropriate here because an approximate day count feeds a reminder email, not a ledger entry. The same clamping logic applies to rent schedules, payroll, and recurring calendar events.
function getNextBillingDate(startDate, billingDay) {
const now = new Date();
const billing = new Date(now.getFullYear(), now.getMonth(), billingDay);
// If billing day has passed this month, move to next month
if (billing.getDate() < now.getDate() || billing < now) {
billing.setMonth(billing.getMonth() + 1);
}
// Handle months with fewer days (e.g., billing day 31 in February)
const lastDayOfMonth = new Date(billing.getFullYear(), billing.getMonth() + 1, 0).getDate();
if (billingDay > lastDayOfMonth) {
billing.setDate(lastDayOfMonth);
}
return {
nextBilling: billing.toLocaleDateString(),
daysUntilBilling: Math.ceil((billing - now) / (1000 * 60 * 60 * 24))
};
}
console.log(getNextBillingDate('2024-01-15', 15));
// { nextBilling: '3/15/2024', daysUntilBilling: 10 }