Dates Intl
By the end of this lesson you'll create, read, and format dates correctly — and show times, currencies, and "3 hours ago" the way each user's country expects.
Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
📚 Prerequisites: You should be comfortable with variables and functions . Knowing how objects and methods work will help, since a date is an object with methods.
💡 Running Code Locally: While this online editor runs real JavaScript, some advanced examples may have limitations. For the best experience:
- Download Node.js to run JavaScript on your computer
- Use your browser's Developer Console (Press F12) to test code snippets
- Create a .html file with <script> tags and open it in your browser
🕰️ Real-World Analogy: A Date is like the single counter on a stopwatch that started ticking at midnight on Jan 1, 1970 (UTC) :
- • Inside, it only stores one number — how many milliseconds have ticked by
- • The clock on your wall (local time) is just that number shown in your zone
- • Two people in different countries read the same instant as different wall-clock times
- • Intl is the translator that prints that instant the way each country writes it
1️⃣ The Date Object: One Number Underneath
A Date is JavaScript's built-in type for a moment in time. It does not store a time zone. It stores a single number: the milliseconds since the epoch (midnight, Jan 1 1970, UTC). Every other thing you see — local time, ISO strings, formatted text — is calculated from that number.
You create "now" with new Date() , read the raw number with getTime() , and get a universal string with toISOString() .
2️⃣ Creating & Parsing Dates Safely
There are three reliable ways to build a date. The safest take the guesswork out of which time zone JavaScript should assume. Notice the month is zero-indexed in the numeric constructor — 0 is January, 11 is December.
3️⃣ Reading & Changing Parts of a Date
Each piece has a get method and a matching set method: getFullYear() , getMonth() , getDate() (day of month), getDay() (day of week, 0 = Sunday), getHours() , and so on. The set methods mutate the date in place and conveniently roll over — adding a day to Jan 31 lands on Feb 1.
🎯 Your Turn #1 — Build a Birthday
Remember: the month in Date.UTC() is zero-indexed. Fill in the blanks.
4️⃣ Timestamps: Bug-Free Date Math
A timestamp is just that millisecond number. Because it's plain arithmetic, adding fixed durations (minutes, hours) is reliable. Date.now() gives the current timestamp directly. To add calendar units like days or months, prefer the set methods, which respect month lengths and daylight saving.
5️⃣ Formatting with Intl.DateTimeFormat
Never build a display string by hand. Intl.DateTimeFormat takes a locale (like "en-US" or "en-GB" ) and an options object, then prints the date the way that country writes it — correct order, month names, and 12- vs 24-hour clock. Pass timeZone to control which zone it renders in.
Intl.NumberFormat — Money & Numbers
The same family formats numbers. With style: "currency" and a currency code, Intl.NumberFormat adds the right symbol, decimals, and grouping for the locale. This is how you show prices correctly to a global audience.
7️⃣ Intl.RelativeTimeFormat — "3 hours ago"
For feeds and notifications, show relative time. Negative numbers are the past, positive are the future. With numeric: "auto" it even says "yesterday" and "tomorrow" where a language has those words.
🎯 Your Turn #2 — Price Tag
Use Intl.NumberFormat to print a euro price for a French audience.
🧩 Mini-Challenge — Event Countdown
Now with the scaffolding removed. Work from the comment outline only.
Time Zones in Practice
Store the instant in UTC; convert only when you display . Pass an IANA zone name (like "America/New_York" ) to timeZone and the formatter handles the offset and daylight saving for you.
📦 A Note on Date Libraries: The built-in Date is fine for the basics, but it is mutable and quirky. Two things worth knowing:
- • date-fns — a popular toolkit of small, pure functions ( addDays , format , differenceInDays ) that never mutate your dates.
- • Temporal — the new standard built into JavaScript, designed to replace Date with immutable, time-zone-aware types. It's rolling out now; learn it when it lands in your runtime.
Common Errors & Fixes
- 1️⃣ Months are off by one
- 2️⃣ "One day off" from an ambiguous string
- 3️⃣ set methods mutate the original
- 4️⃣ Invalid input gives "Invalid Date", not an error
- 5️⃣ Forgetting the time zone when formatting
Quick Reference — Dates & Intl
Task
Code
Now
new Date() / Date.now()
From ISO (UTC)
new Date("2025-06-16T12:00:00Z")
From parts (UTC)
new Date(Date.UTC(2025, 0, 1))
Raw timestamp
d.getTime()
Universal string
d.toISOString()
Read part
d.getUTCFullYear() , getUTCMonth() (0–11)
Format date
new Intl.DateTimeFormat("en-GB", {…}).format(d)
Format currency
new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })
Relative time
new Intl.RelativeTimeFormat("en", { numeric: "auto" }).format(-3, "hour")
Frequently Asked Questions
Lesson Complete — Dates & Internationalization!
- ✅ A Date is one number: milliseconds since the 1970 UTC epoch
- ✅ Months are zero-indexed; prefer ISO strings with Z or Date.UTC()
- ✅ Do math with timestamps; use set methods for calendar units
- ✅ Format with Intl.DateTimeFormat , Intl.NumberFormat , and Intl.RelativeTimeFormat
- ✅ Store in UTC, display in the user's time zone
You can now handle dates the way production apps do — accurately, and in any language. 🌍
Practice quiz
What single value does a Date store internally?
- A formatted local string
- A year, month, and day struct
- Milliseconds since the 1970 UTC epoch
- A time-zone name
Answer: Milliseconds since the 1970 UTC epoch. A Date is one number: milliseconds since midnight Jan 1 1970 UTC; everything else is calculated from it.
In JavaScript Date, which month index represents December?
- 11
- 12
- 1
- 0
Answer: 11. Months are zero-indexed: January is 0 and December is 11.
What does new Date(0).toISOString() produce?
- 2000-01-01T00:00:00.000Z
- The current date
- Invalid Date
- 1970-01-01T00:00:00.000Z
Answer: 1970-01-01T00:00:00.000Z. Timestamp 0 is the Unix epoch: 1970-01-01T00:00:00.000Z.
Which is the recommended, unambiguous way to store a date?
- A bare date-only string like '2025-01-01'
- An ISO string with a 'Z', or Date.UTC()
- new Date(year, month, day) in local time
- A formatted display string
Answer: An ISO string with a 'Z', or Date.UTC(). ISO strings with Z (or Date.UTC) are unambiguous UTC; bare date-only strings can shift by a day locally.
What is the difference between Date.now() and someDate.getTime()?
- Date.now() is static and gives the current time; getTime() reads an existing Date
- They return different units
- getTime() returns a string
- Date.now() needs a new Date first
Answer: Date.now() is static and gives the current time; getTime() reads an existing Date. Both return milliseconds since the epoch; Date.now() is static, getTime() is called on an instance.
Do Date set methods like setUTCDate mutate the original Date?
- No, they return a new Date
- Only in strict mode
- Yes, they mutate it in place
- Only for UTC methods
Answer: Yes, they mutate it in place. set methods mutate the date in place (and conveniently roll over month boundaries).
Which Intl object formats a date for a specific locale?
- Intl.NumberFormat
- Intl.DateTimeFormat
- Intl.Collator
- Intl.ListFormat
Answer: Intl.DateTimeFormat. Intl.DateTimeFormat takes a locale and options and prints the date the way that country writes it.
To format a value as currency, which Intl API and option do you use?
- Intl.DateTimeFormat with style 'currency'
- Intl.RelativeTimeFormat
- Number.toCurrency()
- Intl.NumberFormat with style 'currency' and a currency code
Answer: Intl.NumberFormat with style 'currency' and a currency code. Intl.NumberFormat with { style: 'currency', currency: 'USD' } adds the right symbol and grouping.
With Intl.RelativeTimeFormat, what does a negative number represent?
- The future
- The past
- An invalid value
- Midnight
Answer: The past. Negative numbers are the past (e.g. -3 'hour' is '3 hours ago'); positive numbers are the future.
What is the recommended strategy for handling time zones?
- Store local time, convert on the server
- Always store the user's offset in minutes
- Store the instant in UTC, convert only when displaying
- Avoid UTC entirely
Answer: Store the instant in UTC, convert only when displaying. Store instants in UTC and convert to the user's zone only at display time via a timeZone option.
Continue this course
- Previous: Regular Expressions Advanced Techniques
- Next: Back to Course