Numbers and Dates

In JavaScript, there is only one number type for both integers and decimals. Whether you write 5 or 5.5, both are of type number.

javascript

let age = 25;
let price = 9.99;

console.log(typeof age);   // number
console.log(typeof price); // number

JavaScript stores all numbers as 64-bit floating point values (following the IEEE 754 standard). This means that sometimes arithmetic with decimals can give surprising results.

javascript

console.log(0.1 + 0.2); // 0.30000000000000004 (not exactly 0.3)

// Fix: round the result
console.log((0.1 + 0.2).toFixed(1)); // "0.3"

This is not a bug in JavaScript. It is a natural result of how floating point numbers are stored in binary.

You often need to convert strings to numbers or numbers to strings. JavaScript provides several ways to do this.

javascript

// String to Number
console.log(Number("42"));    // 42
console.log(Number("3.14"));  // 3.14
console.log(Number(""));      // 0
console.log(Number("abc"));   // NaN

// Number to String
console.log(String(42));      // "42"
console.log((42).toString()); // "42"

// Unary + operator (quick conversion)
console.log(+"55");  // 55
console.log(+"");    // 0

JavaScript supports four number systems using special prefixes. All of them are stored as regular numbers internally.

Binary (Base 2)

Uses digits 0 and 1. Prefix: 0b

javascript

let binary = 0b1010; // binary for 10
console.log(binary); // 10

Octal (Base 8)

Uses digits 0 to 7. Prefix: 0o

javascript

let octal = 0o17; // octal for 15
console.log(octal); // 15

Decimal (Base 10)

The everyday number system we use. No prefix needed.

javascript

let decimal = 255;
console.log(decimal); // 255

Hexadecimal (Base 16)

Uses digits 0-9 and letters a-f. Prefix: 0x. Widely used in colors and memory addresses.

javascript

let hex = 0xff; // hexadecimal for 255
console.log(hex); // 255

JavaScript provides built-in methods to check whether a value is a valid number, an integer, or a finite number.

javascript

console.log(Number.isNaN(NaN));       // true
console.log(Number.isNaN(42));        // false
console.log(Number.isNaN("hello"));   // false (use this over global isNaN)

console.log(Number.isFinite(100));    // true
console.log(Number.isFinite(Infinity)); // false

console.log(Number.isInteger(5));     // true
console.log(Number.isInteger(5.5));   // false

Always prefer Number.isNaN() over the global isNaN(), because the global version coerces the value to a number first, which can give unexpected results.

The built-in Math object provides utility functions for mathematical operations, including rounding, square roots, powers, and more.

javascript

console.log(Math.round(4.5));  // 5  (rounds to nearest integer)
console.log(Math.floor(4.9));  // 4  (rounds down)
console.log(Math.ceil(4.1));   // 5  (rounds up)
console.log(Math.trunc(4.7));  // 4  (removes decimal part)

console.log(Math.sqrt(16));    // 4
console.log(Math.pow(2, 8));   // 256
console.log(Math.abs(-10));    // 10
console.log(Math.max(1, 5, 3)); // 5
console.log(Math.min(1, 5, 3)); // 1
console.log(Math.random());    // random number between 0 and 1

To get a random integer between two values:

javascript

// Random integer between min and max (inclusive)
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandomInt(1, 10)); // e.g. 7

The remainder operator % returns the leftover after dividing two numbers. It is commonly used to check if a number is even or odd.

javascript

console.log(10 % 3); // 1  (10 divided by 3 leaves remainder 1)
console.log(8 % 2);  // 0  (8 divided by 2 leaves no remainder)

// Check even or odd
let n = 7;
if (n % 2 === 0) {
  console.log("Even");
} else {
  console.log("Odd"); // Output: Odd
}

Numeric separators (_) were introduced in ES2021 to make large numbers easier to read. They are purely visual and do not affect the value.

javascript

// Without separator - hard to read
let salary = 1000000;

// With separator - easy to read
let salary2 = 1_000_000;

console.log(salary === salary2); // true (same value)

// Works with decimals and other number types
let price = 1_234.56_78;
let binary = 0b1010_0001;
let hex = 0xFF_FF_FF;

BigInt is a special numeric type introduced in ES2020. It lets you work with integers larger than Number.MAX_SAFE_INTEGER (which is 253 - 1).

You create a BigInt by adding n at the end of a number, or by calling BigInt().

javascript

const big = 9007199254740991n;
const big2 = BigInt(9007199254740991);

console.log(typeof big);  // bigint
console.log(big + 1n);    // 9007199254740992n

You can use all standard arithmetic operators with BigInt, but both operands must be BigInt. Division always returns a whole number (no decimals).

javascript

console.log(10n + 5n);  // 15n
console.log(10n - 5n);  // 5n
console.log(10n * 5n);  // 50n
console.log(10n / 3n);  // 3n  (decimal part is dropped)
console.log(10n % 3n);  // 1n

// Comparison works across types
console.log(10n === 10);  // false (different types)
console.log(10n == 10);   // true  (loose equality)

BigInt has a few important limitations to keep in mind.

javascript

// Cannot mix BigInt with regular numbers in arithmetic
console.log(10n + 5);  // TypeError: Cannot mix BigInt and other types, use explicit conversions

// Math methods do not work with BigInt
console.log(Math.sqrt(16n)); // TypeError: Cannot convert a BigInt value to a number

// BigInt cannot be used where a floating point is expected
const x = 1.5n; // SyntaxError: Invalid or unexpected token

// To convert BigInt to Number (may lose precision for very large values)
console.log(Number(42n)); // 42

Number instances have several useful methods you can call directly on a number value.

toFixed()

Rounds a number to a specified number of decimal places and returns it as a string.

javascript

let price = 9.8756;
console.log(price.toFixed(2)); // "9.88"
console.log(price.toFixed(0)); // "10"

toString()

Converts a number to a string. You can pass a base (radix) to convert to a different number system.

javascript

let num = 255;
console.log(num.toString());    // "255"   (decimal, default)
console.log(num.toString(2));   // "11111111" (binary)
console.log(num.toString(16));  // "ff"    (hexadecimal)

valueOf()

Returns the primitive number value of a Number object. It is called automatically by JavaScript in most situations.

javascript

let n = new Number(42);
console.log(n.valueOf()); // 42
console.log(typeof n.valueOf()); // "number"

The Number constructor also has static functions that help with parsing and checking values.

parseInt()

Parses a string and returns an integer. It stops reading at the first non-numeric character.

javascript

console.log(parseInt("42px"));    // 42
console.log(parseInt("3.9"));     // 3  (decimal part dropped)
console.log(parseInt("abc"));     // NaN
console.log(parseInt("0xff", 16)); // 255 (parse hex)

parseFloat()

Parses a string and returns a floating point number.

javascript

console.log(parseFloat("3.14em")); // 3.14
console.log(parseFloat("42"));    // 42
console.log(parseFloat("abc"));   // NaN

isNaN()

Number.isNaN() checks strictly whether a value is NaN without coercing it. This is different from the global isNaN().

javascript

console.log(Number.isNaN(NaN));       // true
console.log(Number.isNaN(undefined)); // false
console.log(Number.isNaN("abc"));     // false

// Global isNaN coerces the value first (less reliable)
console.log(isNaN("abc")); // true  (coerces "abc" to NaN first)

The Number object has several constant properties that represent important numeric boundary values.

javascript

// Largest representable number
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308

// Smallest positive number greater than 0
console.log(Number.MIN_VALUE); // 5e-324

// Largest safe integer (2^53 - 1)
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991

// Smallest safe integer (-(2^53 - 1))
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991

// Positive and Negative Infinity
console.log(Number.POSITIVE_INFINITY); // Infinity
console.log(Number.NEGATIVE_INFINITY); // -Infinity
console.log(1 / 0);  // Infinity
console.log(-1 / 0); // -Infinity

// NaN (Not a Number)
console.log(Number.NaN); // NaN
console.log(0 / 0);      // NaN

// Global Infinity (same as Number.POSITIVE_INFINITY)
console.log(Infinity);  // Infinity

The Intl.NumberFormat API lets you format numbers according to the conventions of a specific locale (language and region). This is useful for displaying currencies, percentages, and large numbers in a user-friendly way.

javascript

const num = 1234567.89;

// US English format
console.log(new Intl.NumberFormat("en-US").format(num));
// 1,234,567.89

// German format (uses dots for thousands, comma for decimal)
console.log(new Intl.NumberFormat("de-DE").format(num));
// 1.234.567,89

// Currency formatting
console.log(new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD"
}).format(num));
// $1,234,567.89

// Percentage
console.log(new Intl.NumberFormat("en-US", {
  style: "percent"
}).format(0.75));
// 75%

The Date object in JavaScript is used to work with dates and times. It stores a point in time as the number of milliseconds since January 1, 1970 (UTC), which is called the Unix epoch.

You can use it to get the current date and time, calculate durations, compare dates, and format dates for display.

javascript

const now = new Date();
console.log(now); // Current date and time
console.log(typeof now); // "object"

There are four common ways to create a Date object in JavaScript.

1. Current date and time

Calling new Date() with no arguments gives you the current date and time.

javascript

const now = new Date();
console.log(now); // e.g. Mon Mar 03 2025 10:30:00 GMT+0000

2. From a date string

You can pass a date string in ISO format or a common format.

javascript

const d1 = new Date("2025-01-15");
console.log(d1); // Wed Jan 15 2025

const d2 = new Date("January 15, 2025 10:30:00");
console.log(d2); // Wed Jan 15 2025 10:30:00

3. From individual components

Pass year, month (0-11), day, hours, minutes, seconds, and milliseconds directly. Month starts at 0 (January = 0, December = 11).

javascript

// new Date(year, month, day, hours, minutes, seconds, ms)
const d = new Date(2025, 0, 15, 10, 30, 0);
// month 0 = January
console.log(d); // Wed Jan 15 2025 10:30:00

4. From a timestamp (milliseconds)

Pass the number of milliseconds since the Unix epoch.

javascript

const d = new Date(0);
console.log(d); // Thu Jan 01 1970 00:00:00 (Unix epoch)

const d2 = new Date(1_000_000_000_000);
console.log(d2); // Sat Sep 09 2001 01:46:40

JavaScript stores dates as milliseconds since the Unix epoch. There are 1000 milliseconds in a second. Knowing this helps you convert between time units.

javascript

const now = new Date();

// Get timestamp (ms since Unix epoch)
console.log(now.getTime()); // e.g. 1741000000000

// Time unit conversions
const ms = 1000;
const seconds = ms * 60;       // 60,000 ms = 1 minute
const minutes = seconds * 60;  // 3,600,000 ms = 1 hour
const hours = minutes * 24;    // 86,400,000 ms = 1 day

// Calculate days between two dates
const date1 = new Date("2025-01-01");
const date2 = new Date("2025-03-01");
const diffMs = date2 - date1;
const diffDays = diffMs / hours;
console.log(diffDays); // 59

You can also use Date.now() to quickly get the current timestamp without creating a Date object.

javascript

console.log(Date.now()); // current timestamp in ms

Getter methods let you read individual parts of a date such as year, month, day, hour, and so on.

javascript

const d = new Date("2025-03-15T10:30:45.500");

console.log(d.getFullYear());     // 2025
console.log(d.getMonth());        // 2  (March, months are 0-indexed)
console.log(d.getDate());         // 15 (day of the month)
console.log(d.getDay());          // 6  (Saturday, 0=Sunday)
console.log(d.getHours());        // 10
console.log(d.getMinutes());      // 30
console.log(d.getSeconds());      // 45
console.log(d.getMilliseconds()); // 500
console.log(d.getTime());         // timestamp in ms

Remember: getMonth() returns 0 for January and 11 for December. Add 1 when displaying it to users.

Setter methods let you change individual parts of an existing date object. This is useful when you want to adjust a date rather than create a new one.

javascript

const d = new Date("2025-01-01");

d.setFullYear(2026);
console.log(d.getFullYear()); // 2026

d.setMonth(5); // June (0-indexed)
console.log(d.getMonth()); // 5

d.setDate(20);
console.log(d.getDate()); // 20

d.setHours(9);
d.setMinutes(15);
d.setSeconds(0);
console.log(d); // 2026-06-20 09:15:00

A common use case is adding days to a date:

javascript

const today = new Date();
today.setDate(today.getDate() + 7); // add 7 days
console.log(today); // one week from now

The Intl.DateTimeFormat API lets you format dates according to a specific locale (language and region). This is great for displaying dates in a way that feels natural to your users.

javascript

const date = new Date("2025-03-15");

// US English
console.log(new Intl.DateTimeFormat("en-US").format(date));
// 3/15/2025

// British English
console.log(new Intl.DateTimeFormat("en-GB").format(date));
// 15/03/2025

// German
console.log(new Intl.DateTimeFormat("de-DE").format(date));
// 15.3.2025

You can also customize the output with options:

javascript

const date = new Date("2025-03-15T10:30:00");

const formatter = new Intl.DateTimeFormat("en-US", {
  weekday: "long",
  year: "numeric",
  month: "long",
  day: "numeric",
  hour: "2-digit",
  minute: "2-digit",
});

console.log(formatter.format(date));
// Saturday, March 15, 2025 at 10:30 AM

To get the user's locale from the browser automatically:

javascript

const userLocale = navigator.language; // e.g. "en-US"
const date = new Date();
console.log(new Intl.DateTimeFormat(userLocale).format(date));
  • JavaScript uses a single number type for both integers and decimals.
  • All numbers are stored as 64-bit floating point (IEEE 754), which can cause small precision errors with decimals.
  • Use Number(), parseInt(), or parseFloat() to convert values to numbers.
  • Number systems: binary (0b), octal (0o), decimal (no prefix), hexadecimal (0x).
  • Use Number.isNaN(), Number.isFinite(), and Number.isInteger() to check number values.
  • The Math object provides rounding (round, floor, ceil), sqrt, pow, abs, and random.
  • The remainder operator % returns what is left after division.
  • Numeric separators (_) make large numbers easier to read without affecting their value.
  • BigInt handles integers beyond Number.MAX_SAFE_INTEGER. Cannot be mixed with regular numbers in arithmetic.
  • Number methods: toFixed() for rounding to decimals, toString() for base conversion, valueOf() for the primitive value.
  • Key Number properties: MAX_VALUE, MIN_VALUE, POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN.
  • Use Intl.NumberFormat to display numbers in locale-specific formats including currency and percentage.
  • The Date object stores time as milliseconds since the Unix epoch (Jan 1, 1970).
  • Create dates with new Date(), a date string, individual components, or a timestamp.
  • Getter methods like getFullYear(), getMonth(), getDate() read parts of a date. Note: months are 0-indexed.
  • Setter methods like setFullYear(), setMonth(), setDate() change parts of a date.
  • Use Intl.DateTimeFormat to format dates according to any locale and with custom options.