webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Tooling
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Forms
  12. 12Data and backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animations
  16. 16Testing
  17. 17Architecture
JavaScript · Lesson 7 of 17

Dates and time

Timestamps, UTC vs local, Date's traps, calculations and formatting with Intl.

Updated

What a Date is in JavaScript

A Date object represents a moment in time — internally, just a number: the milliseconds since January 1, 1970, 00:00 UTC (a timestamp).

const now = new Date()
now.getTime()          // 1791460800000 — the timestamp
Date.now()             // the same thing, without an object

Everything you see as "October 8, 2:30 PM" is an interpretation of that number in a time zone. That's where almost all date bugs come from.

UTC vs local time

UTC Local time
What it is the universal reference time, no time zone the time in the device's time zone (New York: UTC−5 in winter, UTC−4 in summer)
Where you use it storage, APIs, databases only for display
Methods getUTCHours(), toISOString() getHours(), toLocaleString()

The golden rule: store and transmit in UTC (ISO 8601), display in local time.

new Date().toISOString()   // '2026-10-08T11:30:00.000Z' — Z = UTC

Creating a date — the traps

Code Result Trap
new Date('2026-10-08') midnight UTC in New York it shows the evening of October 7
new Date('2026-10-08T10:00') local time no Z = local
new Date('2026-10-08T10:00Z') UTC time explicit, safe
new Date(2026, 9, 8) October 8 months start at 0
new Date('08/10/2026') depends on the browser an ambiguous format — don't use it

Calculations

const DAY = 24 * 60 * 60 * 1000
const diffDays = Math.round((b - a) / DAY)     // subtracting two Dates gives milliseconds

const tomorrow = new Date(date)
tomorrow.setDate(tomorrow.getDate() + 1)      // handles the end of the month correctly

Careful: Date is mutable — setDate changes the object. Copy it first (new Date(date)).

Daylight saving time makes a day last 23 or 25 hours — that's why there's a Math.round on the day difference.

Display with Intl

new Intl.DateTimeFormat('en-US', { dateStyle: 'long' }).format(date)        // 'October 8, 2026'
new Intl.DateTimeFormat('en-US', { dateStyle: 'short', timeStyle: 'short' }).format(date)
new Intl.DateTimeFormat('en-US', { timeZone: 'Europe/London', timeStyle: 'short' }).format(date)

new Intl.RelativeTimeFormat('en', { numeric: 'auto' }).format(-1, 'day')     // 'yesterday'
new Intl.RelativeTimeFormat('en', { numeric: 'auto' }).format(3, 'day')      // 'in 3 days'

Dates in Next.js — hydration

A date formatted on the server (the server's time zone, usually UTC) and again on the client (the user's time zone) can produce different text → a hydration error. Solutions: format with a fixed timeZone, or show relative / local time only in a Client Component, after mounting.

Libraries and the future

Option When
Date + Intl most applications
date-fns lots of calculations (add months, start of week) — small, tree-shakable functions
Temporal (native, new) a modern, immutable API with correct time zones — the replacement for Date, rolling out to browsers

Summary

  • Date = a UTC timestamp; everything else is an interpretation in a time zone.
  • Store in UTC / ISO, display locally with Intl; months start at 0; Date is mutable.
  • Watch out for hydration in Next; date-fns for calculations, Temporal for the future.

Official sources

Exercises

Was this page helpful?

One tap — no account needed.