Chapter 27 of 28 · JavaScript for Beginners — Complete Free Tutorial

Dates, Math & Numbers

The standard library ships with powerful built-ins for the three things every app eventually needs: dates (timestamps, formatting, diffs), math (rounding, randomness, ranges) and number formatting (currency, percentages, precision). Knowing these saves you from installing a library for tasks one line long.

Dates: creating

const now  = new Date();                  // current date-time (local timezone)
const ymd  = new Date(2026, 2, 5);        // 5 March 2026 — month is 0-indexed!
const iso  = new Date('2026-03-05T10:30:00Z');
const fromMs = new Date(1772889000000);   // from epoch milliseconds

console.log(now.getFullYear());           // → 2026
console.log(now.getMonth());              // → 0-11 (January = 0 😬)
console.log(now.getDate());               // → day of month
console.log(now.getHours());              // → local hour
console.log(now.toISOString());           // → '2026-03-05T10:30:00.000Z' (UTC, standard)

The zero-based month is JavaScript's most famous date gotcha. toISOString() always gives UTC — the format APIs and servers expect.

Dates: comparing, diffing, adding

const start = new Date('2026-01-01');
const end   = new Date('2026-03-05');

// difference — dates convert to epoch milliseconds in arithmetic
const days = Math.round((end - start) / 86_400_000);
console.log(days);                          // → 63

// add 7 days
const next = new Date(start);
next.setDate(next.getDate() + 7);

// comparisons
console.log(end > start);                   // → true (value comparison works)
console.log(start.getTime());               // → raw number for exact work

Rule: do date math in numbers (getTime(), milliseconds), never by parsing display strings.

Formatting dates

const d = new Date(2026, 2, 5);

console.log(d.toLocaleDateString('en-IN', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }));
// → 'Wednesday, 5 March 2026' (locale-aware)

console.log(d.toLocaleTimeString('en-IN', { hour: '2-digit', minute: '2-digit' }));
// → '05:30 pm' style per locale

const fmt = new Intl.DateTimeFormat('en-IN', { dateStyle: 'medium' });
console.log(fmt.format(d));                 // → '5 Mar 2026'

Prefer Intl over hand-rolled concatenation — it handles locale ordering, month names and numerals. For storage and APIs, keep ISO strings; format only at the display edge.

Math: the essentials

console.log(Math.floor(4.9));    // → 4  (round down)
console.log(Math.ceil(4.1));     // → 5  (round up)
console.log(Math.round(4.5));    // → 5  (half up)
console.log(Math.trunc(-4.9));   // → -4 (drop decimals, keep sign)
console.log(Math.abs(-7));       // → 7
console.log(Math.min(3, 9, 1));  // → 1
console.log(Math.max(3, 9, 1));  // → 9
console.log(Math.pow(2, 10));    // → 1024 (or 2 ** 10)
console.log(Math.sqrt(81));      // → 9
console.log(Math.hypot(3, 4));   // → 5 (right-triangle distance)

Random numbers

console.log(Math.random());                     // → 0 ≤ x < 1

// integer in [min, max] inclusive
const randInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
console.log(randInt(1, 6));                     // → dice roll 1-6

// pick from a list
const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];

Math.random() is not cryptographic — for tokens, IDs or anything security-relevant use crypto.randomUUID() / crypto.getRandomValues().

Numbers: precision and formatting

console.log((0.1 + 0.2).toFixed(2));   // → '0.30' (string! — remember float quirks)
console.log(Number((0.1 + 0.2).toFixed(2)) === 0.3);  // → true after rounding

console.log(parseInt('42abc', 10));    // → 42 (base 10 explicit)
console.log(parseFloat('3.5m'));       // → 3.5
console.log(Number('  12  '));         // → 12 (trims); Number('') is 0 ⚠️

console.log(Number.isNaN(NaN));        // → true (strict — unlike global isNaN)
console.log(Number.isFinite(1 / 0));   // → false
console.log((1234567).toString());     // → '1234567'
console.log((255).toString(16));       // → 'ff' (any radix 2-36)

Intl.NumberFormat: currency and percent done right

const inr = new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR', maximumFractionDigits: 2 });
console.log(inr.format(123456.789));    // → ₹1,23,456.79 (Indian grouping, automatically)

const usd = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' });
console.log(usd.format(1999.5));        // → $1,999.50

const pct = new Intl.NumberFormat('en-IN', { style: 'percent', maximumFractionDigits: 1 });
console.log(pct.format(0.0735));        // → 7.4%

Expected output: correct grouping, symbols and decimals for any locale — never hand-concatenate currency symbols, and never toFixed alone for display (it returns a string and ignores locale rules).

Useful number utilities

const clamp = (n, min, max) => Math.min(max, Math.max(min, n));   // pin a slider
const lerp  = (a, b, t) => a + (b - a) * t;                       // interpolate 0-1
console.log(clamp(15, 0, 10));   // → 10
console.log(lerp(0, 100, 0.25)); // → 25

// round to n decimals as a NUMBER
const roundTo = (n, d = 2) => Math.round(n * 10 ** d) / 10 ** d;
console.log(roundTo(1.005));     // → 1 (float reality — check expectations)

Temporal? (what's next, briefly)

The newer Temporal API (stage 3, landing gradually) fixes Date's design flaws with immutable, timezone-aware types (Temporal.PlainDate…). Where available, evaluate it for greenfield date-heavy apps; today Date + Intl + toISOString() remains the universal baseline this course teaches.

Common mistakes

  • getMonth() zero-based — 2 means March; add 1 for display, subtract 1 when constructing.
  • Manual string date math — parsing 'DD/MM/YYYY' yourself breaks in other locales; use Date/Intl.
  • Comparing formatted strings — compare getTime() numbers or ISO strings (both sort correctly), never display strings.
  • toFixed for money storage — store minor units (paise) or decimals; format only for display.
  • Local vs UTC mix-ups — a date built from '2026-03-05' (no time) parses as UTC midnight, then displays a day earlier in negative offsets; add a time component ('2026-03-05T00:00:00') when you mean “local midnight”.
  • Math.random() for secrets — predictable; use crypto.

Practice checklist

  1. Write timeAgo(date): “just now”, “5m ago”, “3h ago”, “2d ago”.
  2. Format a list of prices with Intl.NumberFormat in two locales and compare outputs.
  3. Build a randInt-based dice roller UI that rolls on click (DOM + events + math).
  4. Compute the number of days between two user-picked dates with <input type="date">.

These built-ins complete your toolkit. Final chapter: pulling everything together — JavaScript Best Practices & Where to Go Next.

Quiz: Dates, Math & Numbers

5 questions · 70% to pass

Frequently Asked Questions

JavaScript is the programming language of the web. It adds behaviour to pages: responding to clicks and input, validating forms, fetching data from APIs, updating the DOM without reloading, and much more. It also runs on servers (Node.js), in desktop and mobile apps, and in build tooling.

They are unrelated languages that share a similar name for historical marketing reasons. Java is a statically-typed compiled language; JavaScript is a dynamically-typed interpreted language designed for the browser. Knowing one does not imply knowledge of the other.

Helpful but not mandatory — HTML gives you the structure JavaScript manipulates and CSS the styling it toggles. If you know basic tags, classes and selectors, you have enough to start; the DOM chapters assume only that much.

Use const by default and let when the value must change. Avoid var entirely in modern code: it is function-scoped instead of block-scoped, hoists differently, and can create accidental globals. This course uses const and let throughout.

The Document Object Model is the browser’s in-memory tree of objects representing your HTML. JavaScript reads and modifies that tree — selecting elements, changing text, adding nodes, attaching event listeners — and the browser re-renders the page to match.

== compares after converting types (so 5 == "5" is true), while === requires the same value AND the same type (5 === "5" is false). Loose equality has famously confusing rules — use === and !== everywhere unless you have a specific reason not to.

JavaScript is single-threaded, so long-running work (timers, fetches, events) is handled by the browser and its callbacks are queued. The event loop moves queued callbacks onto the call stack only when it is empty, with promise callbacks (microtasks) taking priority over timers. It is why asynchronous code never freezes the page.

A Promise is an object representing a future value — pending, fulfilled or rejected — that can be chained and combined (Promise.all). async/await is syntax sugar over promises that lets asynchronous code read top-to-bottom with ordinary try/catch error handling.

Yes. Frameworks are built on exactly these fundamentals — components are functions, state is your variable discipline, effects are events, rendering is DOM work. Developers who learn vanilla first understand what the framework is doing and debug far faster.

Type out the examples instead of copying, build small end-to-end projects (expense tracker, weather app, quiz), handle every UI state (loading, empty, success, error), and revisit fundamentals while reading real code. Consistency beats volume — a little most days outpaces occasional marathons.