JavaScript Dates Are Weird
The Date object is confusing. Here are the gotchas and how to handle them.
The Weirdness
Months are 0-indexed
new Date(2025, 0, 1) // January 1, 2025
new Date(2025, 11, 1) // December 1, 2025
Why?! Because reasons.
Parsing is inconsistent
new Date("2025-01-15") // UTC midnight
new Date("2025/01/15") // Local midnight
new Date("January 15, 2025") // Local midnight
// Different results depending on your timezone!
Mutation
const date = new Date();
const nextWeek = date;
nextWeek.setDate(date.getDate() + 7);
// BOTH are now next week! Assignment doesn't copy.
Basic Operations
Create Dates
// Current time
const now = new Date();
// Specific date (months are 0-indexed!)
const date = new Date(2025, 9, 6); // October 6, 2025
// From ISO string
const date2 = new Date("2025-10-06T10:00:00Z");
// From timestamp
const date3 = new Date(1728208800000);
Get Parts
date.getFullYear() // 2025
date.getMonth() // 9 (October, remember 0-indexed)
date.getDate() // 6
date.getDay() // 1 (Monday, 0 is Sunday)
date.getHours() // varies by timezone
date.getTime() // timestamp in ms
Format (Modern Way)
const date = new Date("2025-10-06");
// Built-in formatting
date.toLocaleDateString("en-US")
// "10/6/2025"
date.toLocaleDateString("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
})
// "Monday, October 6, 2025"
new Intl.DateTimeFormat("en-US", {
dateStyle: "full",
timeStyle: "short"
}).format(date)
// "Monday, October 6, 2025 at 10:00 AM"
Libraries
For complex date logic, use a library:
date-fns
import { format, addDays, differenceInDays } from "date-fns";
format(new Date(), "yyyy-MM-dd")
// "2025-10-06"
addDays(new Date(), 7)
// Date object for next week
differenceInDays(dateA, dateB)
// Number of days between dates
Day.js (Moment.js successor)
import dayjs from "dayjs";
dayjs().format("YYYY-MM-DD")
// "2025-10-06"
dayjs().add(7, "day").format()
// ISO string for next week
dayjs("2025-01-01").diff(dayjs(), "day")
// Days until January 1
Best Practices
1. **Store as ISO strings or timestamps** - Avoid ambiguity 2. **Convert at the edges** - Parse on input, format on display 3. **Be timezone-aware** - Use UTC for storage 4. **Use libraries for logic** - Don't reinvent date math 5. **Test with different timezones** - Set TZ env var in tests
Dates are hard. Don't feel bad for struggling with them.