Dates, Times and Intl Formatting

Create and read dates with the Date object, add days, compare and measure time, and format dates, numbers and currencies for any country with Intl.

Lesson 31 of 56Intermediate15 min read

Dates are everywhere in web apps: order times, event countdowns, "posted 3 hours ago" labels, booking calendars and birthdays. JavaScript handles them with the built-in Date object, which stores a single moment in time, and the Intl API, which formats dates, numbers and currencies in the style of any country and language.

Dates are famously tricky in every programming language. Months are numbered from 0, time zones shift the hour, and "31 January plus one month" has no obvious answer. The good news is that a small set of patterns covers almost everything you'll need in everyday projects.

In this lesson you'll create dates, read and change their parts, add and subtract days, work out the difference between two dates, and format them nicely with toLocaleDateString and Intl.DateTimeFormat. You'll also use Intl.NumberFormat for prices, and learn about Temporal, the newer date API arriving in browsers.

Creating dates

CodeCreates
new Date()The current date and time
new Date("2026-03-14")14 March 2026 at midnight UTC (ISO format)
new Date("2026-03-14T09:30")09:30 local time on 14 March 2026
new Date(2026, 2, 14)14 March 2026, local time (month 2 is March)
new Date(0)1 January 1970 UTC, the "epoch"
Date.now()The current time as milliseconds since the epoch (a number)

Internally a date is just a number: milliseconds since 1 January 1970 UTC. Use the ISO format YYYY-MM-DD for date strings; other formats such as "03/14/2026" are read differently by different browsers.

Reading and changing parts

GetSetNotes
getFullYear()setFullYear(2027)Four-digit year
getMonth()setMonth(0)0 = January, 11 = December
getDate()setDate(15)Day of the month, 1 to 31
getDay()not settableDay of the week, 0 = Sunday
getHours(), getMinutes()setHours(9, 30)Local time
getTime()setTime(ms)Milliseconds since the epoch

Setters handle overflow sensibly: setDate(32) in January moves to 1 February, and setDate(0) gives the last day of the previous month. That makes adding days easy: d.setDate(d.getDate() + 7).

Comparing dates and measuring time

Because dates are numbers underneath, you can compare and subtract them:

JavaScript
const start = new Date("2026-06-01");
const end = new Date("2026-06-15");
end > start;                                   // true
const days = (end - start) / (1000 * 60 * 60 * 24); // 14

Use getTime() to check equality: a.getTime() === b.getTime(), because a === b compares objects, not moments. For performance timing, performance.now() is more precise than Date.now().

Formatting with Intl

JavaScript
const d = new Date("2026-03-14T09:30");
d.toLocaleDateString("en-GB");                 // "14/03/2026"
d.toLocaleDateString("en-US");                 // "3/14/2026"
d.toLocaleDateString("en-GB", { weekday: "long", day: "numeric", month: "long" }); // "Saturday 14 March"
d.toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" }); // "09:30"
FormatterExample output
new Intl.DateTimeFormat("de-DE", { dateStyle: "full" })Samstag, 14. März 2026
new Intl.NumberFormat("en-GB", { style: "currency", currency: "GBP" })£1,234.50
new Intl.RelativeTimeFormat("en", { numeric: "auto" }).format(-1, "day")yesterday

Pass undefined as the locale to use the visitor's own browser language.

JavaScript Dates Syntax

Date essentials

const now = new Date();
const d = new Date("2026-12-25");
d.getFullYear(); d.getMonth(); d.getDate(); d.getDay();
d.setDate(d.getDate() + 7);
const diffDays = (b - a) / 86400000;
d.toISOString();
d.toLocaleDateString("en-GB", { dateStyle: "medium" });
new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(19.5);

JavaScript Dates Summary

  • new Date() creates a date; internally it's milliseconds since 1970.
  • Months are 0 to 11 and getDay() starts with Sunday as 0.
  • Setters roll over, so setDate(getDate() + n) adds days safely.
  • Subtracting dates gives milliseconds; divide to get days or hours.
  • toLocaleDateString and Intl format dates, times and currencies for any locale.

JavaScript Dates Examples

Each example runs in the page. Edit the code and press Run to see what changes.

Example 1

Reading the parts of a date

const d = new Date(2026, 6, 4, 18, 5);
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

console.log("Year:", d.getFullYear());
console.log("Month index:", d.getMonth(), "(July)");
console.log("Day of month:", d.getDate());
console.log("Weekday:", days[d.getDay()]);
console.log("Time:", `${d.getHours()}:${String(d.getMinutes()).padStart(2, "0")}`);
console.log("ISO:", d.toISOString().slice(0, 10));
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 1Month 6 is July, because months start at 0.
  2. Line 2An array turns the weekday number into a name.
  3. Line 8padStart adds a leading zero to the minutes.
  4. Line 9The ISO string is in UTC, so the day can differ from local time late at night.
Example 2

Adding days and counting down

function addDays(date, n) {
  const copy = new Date(date);
  copy.setDate(copy.getDate() + n);
  return copy;
}

const order = new Date(2026, 0, 29);
const delivery = addDays(order, 5);
console.log("Delivery:", delivery.toDateString());

const holiday = new Date(2026, 11, 25);
const today = new Date(2026, 11, 1);
const msPerDay = 1000 * 60 * 60 * 24;
const daysLeft = Math.round((holiday - today) / msPerDay);
console.log(`${daysLeft} days until the holiday`);
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 2Copy the date first, so the original isn't changed.
  2. Line 3Adding 5 days to 29 January rolls over into February.
  3. Line 14Subtracting gives milliseconds; dividing turns them into days.
Example 3

Formatting for different countries

const d = new Date(2026, 2, 14, 9, 30);

console.log(d.toLocaleDateString("en-GB"));
console.log(d.toLocaleDateString("en-US"));
console.log(d.toLocaleDateString("en-GB", { weekday: "long", day: "numeric", month: "long", year: "numeric" }));
console.log(new Intl.DateTimeFormat("fr-FR", { dateStyle: "full", timeStyle: "short" }).format(d));

const price = 1234.5;
console.log(new Intl.NumberFormat("en-GB", { style: "currency", currency: "GBP" }).format(price));
console.log(new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" }).format(price));

const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
console.log(rtf.format(-1, "day"), "|", rtf.format(3, "week"));
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Lines 3 to 4The UK puts the day first; the US puts the month first.
  2. Line 5Options choose exactly which parts to show and how.
  3. Line 6The same date in French, with the time.
  4. Lines 9 to 10Currency formatting adds symbols and separators for each country.
  5. Lines 12 to 13Relative times such as "yesterday" and "in 3 weeks".

Common JavaScript Dates Mistakes

Forgetting months start at 0

Don't
new Date(2026, 12, 25); // January 2027, not December
Do
new Date(2026, 11, 25); // December
new Date("2026-12-25"); // or use an ISO string

Comparing dates with ===

Don't
new Date("2026-01-01") === new Date("2026-01-01"); // false: two objects
Do
new Date("2026-01-01").getTime() === new Date("2026-01-01").getTime(); // true

Changing the original date by accident

Don't
function nextWeek(d) { d.setDate(d.getDate() + 7); return d; } // changes d
Do
function nextWeek(d) { const c = new Date(d); c.setDate(c.getDate() + 7); return c; }

Date objects are mutable; copy them before changing.

JavaScript Dates in Real Projects

Dates in real apps

Booking sites calculate nights between check-in and check-out by subtracting dates. Social networks show "2 hours ago" with relative time formatting. Shops format prices with Intl.NumberFormat so the same code shows £, € or $ correctly. Libraries such as date-fns and Day.js add helpers, and the new Temporal API, now arriving in browsers, offers immutable dates and proper time zone support.

JavaScript Dates Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Get the four-digit year from a date.

const d = new Date("2026-05-20");
console.log(d.());
Predict the outputmedium

What is logged?

const d = new Date(2026, 0, 31);
d.setDate(d.getDate() + 1);
console.log(d.getMonth(), d.getDate());
Multiple choiceeasy

What does getDay() return for a Sunday?

Multiple choicemedium

Which formats 9.5 as "$9.50"?

Fix the bugmedium

daysBetween(a, b) should return the whole number of days from date a to date b, and christmas(year) should return 25 December of that year. Fix both.

function daysBetween(a, b) {
  return (b - a) / 1000;
}
function christmas(year) {
  return new Date(year, 12, 25);
}
console.log(daysBetween(new Date(2026, 0, 1), new Date(2026, 0, 11)));
console.log(christmas(2026).toDateString());
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Ten days apart
  • Christmas is in December
  • Same year

JavaScript Dates Quiz

5 questions to check what you learned.

  1. What does new Date() give you?

    • 1 January 1970
    • An empty date
    • The current date and time
    • An error
  2. What is a JavaScript date stored as internally?

    • A string
    • Seconds since the year 0
    • An array of numbers
    • Milliseconds since 1 January 1970 UTC
  3. Which date string format is safest to parse?

    • "03/14/2026"
    • "2026-03-14"
    • "14 March 26"
    • "March the 14th"
  4. How do you add 7 days to date d?

    • d + 7
    • d.addDays(7)
    • d.setDate(d.getDate() + 7)
    • d.getDate() + 7
  5. Why store dates as UTC ISO strings?

    • They mean the same moment everywhere, whatever the time zone
    • They're shorter
    • Browsers can't read local times
    • JSON doesn't support numbers

JavaScript Dates Challenge

An order summary

Write orderSummary(ordered) where ordered is a Date:

  1. Work out delivery as 3 days after ordered, without changing ordered
  2. Format delivery with toLocaleDateString("en-GB", { weekday: "long", day: "numeric", month: "long" })
  3. Return `Arrives ${formatted}`
function orderSummary(ordered) {

}

console.log(orderSummary(new Date(2026, 2, 30)));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Rolls over into April
  • Original date is unchanged
  • Works in another month