Dates and Times

JavaScript ES2024 · ✓ verified by execution on 2026-08-15

Working with dates and times is a notoriously tricky part of programming. Different timezones, daylight savings, leap years, and legacy design decisions mean there are a lot of hidden landmines waiting to trip you up.

In JavaScript, all of this complexity is wrapped up inside the Date object.

The Date Object

To capture a specific moment in time, you instantiate a new Date object. If you call new Date() without any arguments, it takes a snapshot of the exact millisecond your code was executed.

javascript
const current = new Date();
// The exact string changes every millisecond, but it will always be a string!
console.log(typeof current.toISOString() === 'string');
Output
true

It’s important to remember that Date objects are static. Once created, they do not act like live clocks that keep ticking. They are frozen representations of the exact millisecond they were born.

You can extract specific pieces of information from a Date object using its built-in methods. For instance, to get the day of the month or the year, you use getDate() and getFullYear().

javascript
const landing = new Date('1969-07-20T20:17:40Z');

// Get the 4 digit year
console.log(landing.getUTCFullYear());

// Get the day of the month (1-31)
console.log(landing.getUTCDate());
Output
1969
20

[!WARNING] Never use the older .getYear() method. It was designed in the 90s and returns the number of years since 1900, meaning the year 2026 returns as 126! Always use .getFullYear().

The Zero-Indexed Trap

JavaScript’s Date object was written in exactly 10 days in May 1995. Because the creator had to rush, he copied the design of Java’s java.util.Date class verbatim. Unfortunately, he copied its biggest mistake, too.

In JavaScript, months are 0-indexed.

This means January is 0, February is 1, and December is 11. However, the day of the month (getDate()) is completely normal and starts at 1! This inconsistency is the single most common cause of date-related bugs in the language.

Let’s test your intuition. What do you think the following code will print?

Predict the output javascript

Read the code. What exactly will it print? Commit to an answer before you look.

// We extract the month from a date created in January
const newYears = new Date('2026-01-01T00:00:00Z');
console.log(newYears.getUTCMonth());
Output
0

If you guessed 1, you fell into the trap! Because it’s January, the method returns 0. Whenever you display a month to a user, you must almost always add 1 to the result.

The Epoch Timestamp

Sometimes, you don’t care about calendars, months, or timezones. You just want a raw number that represents exactly “when” something happened so you can do math on it (like calculating how long a function took to run).

For this, you use Date.now().

javascript
const start = Date.now();
console.log(typeof start === 'number');
Output
true

The Date.now() method doesn’t return an object. It simply returns a massive integer. This integer represents the Unix Epoch timestamp — the exact number of milliseconds that have passed since midnight on January 1, 1970 (UTC).

javascript · visualize
const timestamp = Date.now();
const dateObject = new Date(timestamp);

Unix Epoch Start 1970-01-01 00:00:00 UTC 1.78 Trillion ms Date.now() 2026-08-15 12:00:00 UTC
Visualizing the Unix Epoch timestamp mapping to a human readable Date.

By working with raw milliseconds, calculating the duration of an event becomes simple arithmetic: endTime - startTime = durationInMilliseconds.

Check yourself

What does Date.now() return?

Reveal answer

The number of milliseconds elapsed since January 1, 1970. — Date.now() returns an integer representing the Unix Epoch timestamp. It does not return an actual object.

What does the getMonth() method return for a date in January?

Reveal answer

0 — Months are zero-indexed in JavaScript. January is 0, and December is 11.

Which method should you use to retrieve the full 4-digit year?

Reveal answer

getFullYear() — getFullYear() returns the actual four digit year (like 2026). The older getYear() returns the number of years since 1900.

Does a Date object continuously update itself to reflect the current time?

Reveal answer

No, it represents a static snapshot of the exact millisecond it was created. — A Date object acts like a frozen snapshot in time. Once instantiated, its internal timestamp never changes.

Challenges

🐞 Bug Hunt +15 XP

This function is supposed to return a human-readable month number (1-12) from a Date object, but it's returning 0 for January. Fix it.

This code runs. It just does the wrong thing. Read it, find the defect, fix it — the tests below decide when you are right.

javascript
  • Test 1 (input: "2026-01-15T12:00:00Z") — expects "1"
  • Test 2 (input: "2026-12-15T12:00:00Z") — expects "12"
Need a hint? (−25% XP)

Remember that getMonth() is 0-indexed. Add 1 to the result.

Show solution (0 XP)
import fs from 'node:fs';
const d = new Date(fs.readFileSync(0, 'utf-8').trim());

function getHumanMonth(dateObj) {
  return dateObj.getUTCMonth() + 1;
}

console.log(getHumanMonth(d));

Challenge 2 +10 XP

The legacy code below uses a deprecated method to get the year, which is causing a Y2K bug. Replace the deprecated method with the modern equivalent.

javascript
  • Test 1 (input: "2026-08-15T12:00:00Z") — expects "2026"
Need a hint? (−25% XP)

Use getUTCFullYear() instead of getYear().

Show solution (0 XP)
import fs from 'node:fs';
const d = new Date(fs.readFileSync(0, 'utf-8').trim());

function getYearSafely(dateObj) {
  return dateObj.getUTCFullYear();
}

console.log(getYearSafely(d));