Theory
'3 months to go' said the wrong number
FestConnect wants a countdown: 'Fest starts in N days'. You create the fest date as new Date(2026, 3, 12) meaning 12 March, run it, and the countdown is a month off. April, not March.
The Date object is a small package that holds a moment in time, with getters to read its parts and setters to change them. It is genuinely useful, but two of its numbers are counted in a way that surprises everyone.
Theory
A clock you can read part by part
A Date is like a clock-calendar you can question one dial at a time: 'which year?', 'which month?', 'which date?', 'what hour?'. Each getter reads one dial. The catch is that the month dial is printed starting at 0 (January is the 0 mark, not 1), like a floor numbering that starts at 'ground' instead of 'first'. Read the dial, then adjust.
Theory
Create, get, set
- Create:
new Date()is now;new Date(2026, 2, 12)is 12 March 2026 (month 2 = March, because months are 0-indexed). - Getters:
getFullYear(),getMonth()(0 to 11),getDate()(1 to 31, day of month),getDay()(0 to 6, day of week, 0 = Sunday),getHours(). - Setters:
setFullYear(),setMonth(),setDate(),setHours(). - toString(): a readable text form.
There is no setDay: the day of the week is read-only; change the calendar day with setDate.
Practical
FestConnect countdown
// month is 0-indexed: 2 means MARCH, not February
let festDay = new Date(2026, 2, 12); // 12 March 2026
console.log(festDay.getFullYear()); // 2026
console.log(festDay.getMonth()); // 2 (March! add 1 for humans)
console.log(festDay.getDate()); // 12 (day of month)
console.log(festDay.getDay()); // 4 (Thursday: 0=Sun..4=Thu)
let today = new Date();
let msPerDay = 1000 * 60 * 60 * 24;
let daysToGo = Math.ceil((festDay - today) / msPerDay);
console.log("Fest starts in " + daysToGo + " days");
// change a part with a setter
festDay.setDate(14); // move it to 14 MarchThis example runs in Gri-Learn on the web, where you can edit it and see the output.
Think first
getDate or getDay?
For 12 March 2026 (a Thursday), what does getDate() return and what does getDay() return? Students constantly swap these two. Say both before tapping.
Show the answer
getDate() returns 12: the day of the month (1 to 31). getDay() returns 4: the day of the week, counting from Sunday = 0 (so Thu = 4). They sound alike but mean different things: getDate is the calendar number, getDay is which weekday. If you want '12', it is getDate; if you want 'Thursday', it is getDay mapped to a name.
Quiz
You want 12 March 2026. Which constructor call is correct, given how JavaScript counts months?
- new Date(2026, 2, 12), because month 2 = March (0-indexed)
- new Date(2026, 3, 12), because March is the 3rd month
- new Date(12, 3, 2026), day first
- new Date(2026, 03, 12), months must be two digits
Show the answer
new Date(2026, 2, 12), because month 2 = March (0-indexed)
Months are 0-indexed: January is 0, so March is 2, giving new Date(2026, 2, 12) (A). Writing 3 (B) lands on April, the exact off-by-one bug in the hook. The argument order is year, month, day, not day-first (C). And months are plain numbers, not zero-padded (D). Always subtract one from the human month when constructing, and add one when displaying getMonth().
Watch out
Date traps
1. Months are 0-indexed: getMonth() returns 0 for January. Add 1 to display, subtract 1 to construct. This is the number-one Date bug.
2. getDay is not getDate: getDay = weekday (0 to 6), getDate = day of month (1 to 31).
3. No setDay: the weekday is derived, not settable. Use setDate to move to a different day of the month; the weekday updates itself.
Theory
Now put it on the page
Right now the countdown only prints to the console. In the next two lessons you learn the DOM, and you will drop this 'Fest starts in N days' straight into a FestConnect banner element so visitors actually see it. A Date object plus a DOM update is a live countdown, a real feature on many event sites.
Summary
Key takeaways
- A Date object holds a moment; new Date() is now, new Date(2026, 2, 12) is 12 March 2026 (month 0-indexed).
- getFullYear, getMonth (0-11), getDate (1-31, day of month), getDay (0-6, day of week), getHours read the parts.
- setFullYear/setMonth/setDate/setHours change them; toString gives readable text.
- getMonth is 0-indexed: add 1 to display, subtract 1 to construct (the classic bug).
- getDay (weekday) is not getDate (day of month), and there is no setDay.
- Memory hook: month dial starts at 0; getDate = number, getDay = weekday.