Complete JavaScript Course Module 11: Intermediate: Useful Built-in Features

Dates and Timers: Date, setTimeout and setInterval

  • Beginner
  • Lesson 11.1
  • 5 min read
  • 47 of 76 in the course

In short

JavaScript has built-in tools for time. In this lesson you will learn to work with dates using the Date object, format them nicely, and run code later with setTimeout and setInterval. How to create a date in JavaScript A Date object stores one moment in time.

JavaScript has built-in tools for time. In this lesson you will learn to work with dates using the Date object, format them nicely, and run code later with setTimeout and setInterval.

How to create a date in JavaScript

A Date object stores one moment in time. new Date() with no arguments gives you right now. You can also create a specific date in a few ways:

const now = new Date();
console.log(now);
// Output (yours will differ): Thu Oct 01 2026 09:30:12 GMT+0100 (Western European Summer Time)

const birthday = new Date(2026, 0, 15);
console.log(birthday.toDateString());
// Output: Thu Jan 15 2026

const meeting = new Date("2026-03-20T14:30:00");
console.log(meeting.getHours(), meeting.getMinutes());
// Output: 14 30

With numbers, the order is year, month, day (and optionally hours, minutes, seconds). Be careful: months start at 0, so 0 is January and 11 is December. Days of the month start at 1 as normal. With a string, use the ISO format YYYY-MM-DDTHH:mm:ss, which every browser understands.

Common mistake: Writing new Date(2026, 1, 15) and expecting January 15. Month 1 is February. This trips up almost everyone at least once.

Getting parts of a date

Date objects have "getter" methods to read each part:

MethodReturns
getFullYear()The year, e.g. 2026
getMonth()The month, 0 to 11
getDate()The day of the month, 1 to 31
getDay()The day of the week, 0 (Sunday) to 6 (Saturday)
getHours(), getMinutes(), getSeconds()The time parts
getTime()Milliseconds since 1 January 1970 (UTC)
const order = new Date(2026, 0, 15, 9, 5);
const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

console.log(order.getFullYear());
// Output: 2026
console.log(order.getMonth() + 1);
// Output: 1
console.log(weekdays[order.getDay()]);
// Output: Thu
console.log(`${order.getHours()}:${String(order.getMinutes()).padStart(2, "0")}`);
// Output: 9:05

We add 1 to the month for a human-friendly number, and use padStart so the minutes show as 05, not 5.

Formatting dates with toLocaleDateString and Intl.DateTimeFormat

Building date strings by hand is tiring, and every country writes dates differently. The browser can do it for you. toLocaleDateString() takes a locale (a language and region code, like "en-US" or "de-DE") and options.

const launch = new Date(2026, 0, 15);

console.log(launch.toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" }));
// Output: Thursday, January 15, 2026

console.log(launch.toLocaleDateString("de-DE", { weekday: "long", year: "numeric", month: "long", day: "numeric" }));
// Output: Donnerstag, 15. Januar 2026

const short = new Intl.DateTimeFormat("en-GB", { dateStyle: "medium" });
console.log(short.format(launch));
// Output: 15 Jan 2026

const timeOnly = new Intl.DateTimeFormat("en-US", { timeStyle: "short" });
console.log(timeOnly.format(new Date(2026, 0, 15, 18, 45)));
// Output: 6:45 PM

Intl.DateTimeFormat creates a reusable formatter. It is a good choice when you format many dates the same way, like every row in a table. If you leave out the locale (undefined), the browser uses the visitor's own language settings.

Date math basics

Because a date is really a number of milliseconds, you can subtract two dates. The result is a difference in milliseconds, which you can turn into days. To move a date forward, change one part with a "setter" like setDate(); JavaScript handles the month overflow for you.

const MS_PER_DAY = 1000 * 60 * 60 * 24;

const today = new Date(2026, 9, 1);
const christmas = new Date(2026, 11, 25);
const daysLeft = Math.round((christmas - today) / MS_PER_DAY);
console.log(`${daysLeft} days until Christmas`);
// Output: 85 days until Christmas

const trialStart = new Date(2026, 0, 15);
const trialEnd = new Date(trialStart);
trialEnd.setDate(trialEnd.getDate() + 30);
console.log(trialEnd.toDateString());
// Output: Sat Feb 14 2026

We use Math.round because daylight saving time can make one day 23 or 25 hours long. new Date(trialStart) makes a copy, so the original date stays unchanged.

Note: A newer, much friendlier date API called Temporal is arriving in browsers. It fixes many Date problems, such as zero-based months and time zone confusion. Check browser support before you rely on it; Date works everywhere today.

Running code later: setTimeout, setInterval and clearInterval

setTimeout(fn, ms) runs a function once after a delay in milliseconds (1000 ms = 1 second). setInterval(fn, ms) runs it again and again at that interval. Both return an ID number, which you pass to clearTimeout() or clearInterval() to cancel.

console.log("Order placed");

const reminder = setTimeout(() => {
  console.log("Don't forget to check your email!");
}, 2000);

// Change your mind? Cancel it before it runs:
// clearTimeout(reminder);

console.log("This line runs first");
Order placed
This line runs first
Don't forget to check your email!

The last line appears after two seconds. JavaScript does not stop and wait; it schedules the function and carries on.

Example: a countdown timer

<!DOCTYPE html>
<html lang="en">
  <body>
    <p>Offer ends in <strong id="timer">10</strong> seconds</p>
    <button id="stop">Stop timer</button>

    <script>
      const timerText = document.querySelector("#timer");
      let secondsLeft = 10;

      const intervalId = setInterval(() => {
        secondsLeft -= 1;
        timerText.textContent = secondsLeft;

        if (secondsLeft === 0) {
          clearInterval(intervalId);
          timerText.textContent = "0 - the offer has ended";
          console.log("Countdown finished");
        }
      }, 1000);

      document.querySelector("#stop").addEventListener("click", () => {
        clearInterval(intervalId);
        console.log(`Stopped with ${secondsLeft} seconds left`);
      });
    </script>
  </body>
</html>
Countdown finished

Every second, the number goes down by one. At zero we call clearInterval so the timer stops; without it, the count would go into negative numbers. The button stops the timer early.

Tip: Timers are not perfectly exact. The browser may run them a little late, especially in background tabs. For a precise clock, calculate the time left from the end date on each tick instead of counting ticks.

Practice exercise

Show a live clock on a page. Every second, update a <p> with the current time formatted by Intl.DateTimeFormat with { timeStyle: "medium" }. Below it, show how many days are left until your next birthday.

Hint: Create the formatter once, outside setInterval, and call formatter.format(new Date()) inside it.

Key takeaways

  • new Date() gives the current moment; in new Date(year, month, day) the month starts at 0.
  • Use getters like getFullYear() and getDay() to read parts of a date.
  • Format dates for people with toLocaleDateString or Intl.DateTimeFormat.
  • Subtracting dates gives milliseconds; setDate() moves a date forward or back.
  • setTimeout runs code once later, setInterval repeats it, and clearInterval stops it.