|

JavaScript 48 🧬 Date and time

const now = new Date();
console.log(now);

const specific = new Date('2024-01-15T10:30:00');
console.log(specific);

const fromParts = new Date(2024, 0, 15, 10, 30, 0);
console.log(fromParts);

const timestamp = Date.now();
console.log(timestamp);

console.log(now.getFullYear());
console.log(now.getMonth());
console.log(now.getDate());
console.log(now.getDay());
console.log(now.getHours());
console.log(now.getMinutes());
console.log(now.getSeconds());
console.log(now.getMilliseconds());
console.log(now.getTime());

now.setFullYear(2025);
now.setMonth(5);
now.setDate(20);

console.log(now.toISOString());
console.log(now.toDateString());
console.log(now.toTimeString());
console.log(now.toLocaleDateString());
console.log(now.toLocaleTimeString());
console.log(now.toLocaleString());

const d1 = new Date('2024-01-15');
const d2 = new Date('2024-06-20');
console.log(d2 - d1);

console.log(Date.parse('2024-01-15'));
console.log(Date.UTC(2024, 0, 15));

The Date object represents a single moment in time. It’s been in JavaScript since the beginning, and it carries some quirks — zero-indexed months, mutable objects, inconsistent parsing. But it’s also unavoidable, because every application eventually needs to show, compare, or manipulate dates.

Key point: A Date is stored as milliseconds since the Unix epoch — January 1, 1970, 00:00:00 UTC. Everything else (year, month, day, timezone) is derived from that single number. Understanding this makes the API much less mysterious.


a – What is a Date

A Date object represents a point in time. Internally it’s a single number: milliseconds since the epoch.

Creating a Date:

FormExampleMeaning
Currentnew Date()Right now
From stringnew Date('2024-01-15')Parsed
From partsnew Date(2024, 0, 15)Year, month, day
From timestampnew Date(1705314600000)Milliseconds since epoch
From another Datenew Date(otherDate)Copy

Current time:

const now = new Date();
console.log(now);
// [ 2024-01-15T10:30:00.000Z ]

This is the current moment — with milliseconds precision.

From a string:

const d1 = new Date('2024-01-15');
console.log(d1);
// [ 2024-01-15T00:00:00.000Z ]

const d2 = new Date('2024-01-15T10:30:00');
console.log(d2);
// [ 2024-01-15T10:30:00.000Z ]

const d3 = new Date('January 15, 2024');
console.log(d3);
// [ 2024-01-15T00:00:00.000Z ]

⚠️ Warning: Date string parsing is implementation-dependent. '2024-01-15' is treated as UTC in modern engines, but '2024/01/15' or 'January 15, 2024' may be local time. For reliable parsing, use ISO 8601 format (YYYY-MM-DDTHH:mm:ss) or Date.parse() with explicit timezone. For critical code, avoid parsing strings — build from parts.

From parts:

const d = new Date(2024, 0, 15, 10, 30, 0, 0);
console.log(d);
// [ 2024-01-15T10:30:00.000Z ] (in UTC timezone)
ArgumentMeaningRange
YearFull year
Month0-indexed (0 = Jan)0–11
DayDay of month1–31
Hours24-hour0–23
Minutes0–59
Seconds0–59
Milliseconds0–999

Note: Month is 0-indexed! January is 0, December is 11. This is one of the most common sources of bugs.

From a timestamp:

const epoch = new Date(0);
console.log(epoch);
// [ 1970-01-01T00:00:00.000Z ]

const ts = new Date(1705314600000);
console.log(ts);
// [ 2024-01-15T10:30:00.000Z ]

Date.now() — current timestamp in milliseconds:

console.log(Date.now());
// [ 1705314600000 ]

Faster than new Date().getTime() — no object allocation.

The epoch concept:

┌──────────────────────────────────────────────┐
│                                              │
│  1970-01-01T00:00:00 UTC                     │
│              │                               │
│              │  milliseconds                 │
│              ▼                               │
│  ┌────────────────────────┐                  │
│  │  0                     │  ← epoch         │
│  │  1000                  │  ← 1 second later│
│  │  1705314600000         │  ← 2024-01-15    │
│  │  -1000                 │  ← 1 second before│
│  └────────────────────────┘                  │
│                                              │
│  A Date is just a number                     │
│                                              │
└──────────────────────────────────────────────┘

Dates are mutable:

const d = new Date('2024-01-15');
d.setFullYear(2025);
console.log(d);
// [ 2025-01-15T00:00:00.000Z ]

Unlike strings and numbers, Date objects change in place. This is a common source of bugs.

Invalid dates:

const bad = new Date('not a date');
console.log(bad);
// [ Invalid Date ]

console.log(isNaN(bad));
// [ true ]

console.log(bad.getTime());
// [ NaN ]

An Invalid Date is a Date object whose internal number is NaN. Always check with isNaN(date.getTime()).

Timezones:

The Date object has two “views” — UTC and local. Getter methods come in pairs:

LocalUTC
getFullYear()getUTCFullYear()
getMonth()getUTCMonth()
getDate()getUTCDate()
getHours()getUTCHours()
getDay()getUTCDay()

Local methods use your system’s timezone. UTC methods use UTC. The stored timestamp is the same.

const d = new Date('2024-01-15T10:30:00Z');
console.log(d.getHours());       // depends on your timezone
console.log(d.getUTCHours());    // 10

Comparing dates:

const a = new Date('2024-01-15');
const b = new Date('2024-06-20');

console.log(a < b);
// [ true ]

console.log(a > b);
// [ false ]

console.log(a - b);
// [ -13536000000 ]  ← milliseconds difference

Comparison operators work because Dates coerce to numbers. But === compares references:

const a = new Date('2024-01-15');
const b = new Date('2024-01-15');

console.log(a === b);
// [ false ]  ← different objects

console.log(a.getTime() === b.getTime());
// [ true ]  ← same instant

b – Date methods and formatting

The Date API has dozens of methods. This section covers the ones you’ll actually use.

Getters — reading components:

MethodReturns
getFullYear()4-digit year
getMonth()0–11
getDate()1–31
getDay()0–6 (Sunday = 0)
getHours()0–23
getMinutes()0–59
getSeconds()0–59
getMilliseconds()0–999
getTime()Milliseconds since epoch
getTimezoneOffset()Minutes offset from UTC

Reading components:

const d = new Date('2024-01-15T10:30:45.123');

console.log(d.getFullYear());
// [ 2024 ]

console.log(d.getMonth());
// [ 0 ]  ← January

console.log(d.getDate());
// [ 15 ]

console.log(d.getDay());
// [ 1 ]  ← Monday (Sunday = 0)

console.log(d.getHours());
// [ 10 ]

console.log(d.getMinutes());
// [ 30 ]

console.log(d.getSeconds());
// [ 45 ]

console.log(d.getMilliseconds());
// [ 123 ]

console.log(d.getTime());
// [ 1705314645123 ]

Day of week names:

const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
const d = new Date();
console.log(days[d.getDay()]);
// [ Mon ]

Setters — changing components:

MethodMeaning
setFullYear(y)Set year
setMonth(m)Set month (0–11)
setDate(d)Set day
setHours(h)Set hours
setMinutes(m)Set minutes
setSeconds(s)Set seconds
setMilliseconds(ms)Set milliseconds
setTime(ts)Set from timestamp

Setting components:

const d = new Date('2024-01-15');

d.setFullYear(2025);
d.setMonth(5);
d.setDate(20);

console.log(d.toISOString());
// [ 2025-06-20T00:00:00.000Z ]

setDate and month rollover:

const d = new Date('2024-01-31');
d.setMonth(1);   // February
console.log(d.toISOString());
// [ 2024-03-02T00:00:00.000Z ]  ← rolled over

February doesn’t have a 31st, so the Date rolls forward. This is intentional but surprising.

Formatting methods:

MethodOutput
toString()Full string with timezone
toDateString()Date part only
toTimeString()Time part only
toISOString()ISO 8601 UTC
toUTCString()Human-readable UTC
toLocaleString()Localized date + time
toLocaleDateString()Localized date
toLocaleTimeString()Localized time
toJSON()Same as toISOString

Examples:

const d = new Date('2024-01-15T10:30:00');

console.log(d.toString());
// [ Mon Jan 15 2024 10:30:00 GMT+0000 (Coordinated Universal Time) ]

console.log(d.toDateString());
// [ Mon Jan 15 2024 ]

console.log(d.toTimeString());
// [ 10:30:00 GMT+0000 (Coordinated Universal Time) ]

console.log(d.toISOString());
// [ 2024-01-15T10:30:00.000Z ]

console.log(d.toUTCString());
// [ Mon, 15 Jan 2024 10:30:00 GMT ]

console.log(d.toLocaleString());
// [ 1/15/2024, 10:30:00 AM ] (US locale)

console.log(d.toLocaleDateString());
// [ 1/15/2024 ]

console.log(d.toLocaleTimeString());
// [ 10:30:00 AM ]

toLocaleString with options:

const d = new Date('2024-01-15T10:30:00');

console.log(d.toLocaleDateString('en-US', {
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
}));
// [ Monday, January 15, 2024 ]

console.log(d.toLocaleTimeString('en-US', {
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  hour12: false
}));
// [ 10:30:00 ]

Locale options:

OptionValues
weekday'long', 'short', 'narrow'
year'numeric', '2-digit'
month'numeric', '2-digit', 'long', 'short', 'narrow'
day'numeric', '2-digit'
hour'numeric', '2-digit'
minute'numeric', '2-digit'
second'numeric', '2-digit'
hour12true / false
timeZone'UTC', 'America/New_York', etc.
timeZoneName'short', 'long'

Intl.DateTimeFormat — reusable formatter:

const fmt = new Intl.DateTimeFormat('en-US', {
  dateStyle: 'full',
  timeStyle: 'short'
});

console.log(fmt.format(new Date()));
// [ Monday, January 15, 2024 at 10:30 AM ]

Creating a formatter once and reusing it is faster than calling toLocaleString repeatedly.

Intl.RelativeTimeFormat — “2 days ago”:

const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });

console.log(rtf.format(-1, 'day'));
// [ yesterday ]

console.log(rtf.format(2, 'hour'));
// [ in 2 hours ]

console.log(rtf.format(-3, 'month'));
// [ 3 months ago ]

Date arithmetic — no built-in operators:

JavaScript doesn’t have date arithmetic built in. Convert to milliseconds:

const d = new Date('2024-01-15');

// Add 7 days
const nextWeek = new Date(d);
nextWeek.setDate(d.getDate() + 7);
console.log(nextWeek.toISOString());
// [ 2024-01-22T00:00:00.000Z ]

// Add 1 month
const nextMonth = new Date(d);
nextMonth.setMonth(d.getMonth() + 1);
console.log(nextMonth.toISOString());
// [ 2024-02-15T00:00:00.000Z ]

// Add 1 year
const nextYear = new Date(d);
nextYear.setFullYear(d.getFullYear() + 1);
console.log(nextYear.toISOString());
// [ 2025-01-15T00:00:00.000Z ]

Using getTime for arithmetic:

const start = new Date('2024-01-15');
const end = new Date('2024-01-20');

const diffMs = end - start;
const diffDays = diffMs / (1000 * 60 * 60 * 24);

console.log(diffDays);
// [ 5 ]
UnitMilliseconds
Second1000
Minute1000 * 60
Hour1000 * 60 * 60
Day1000 * 60 * 60 * 24
Week1000 * 60 * 60 * 24 * 7

Common date operations:

// Start of today
const today = new Date();
today.setHours(0, 0, 0, 0);

// End of today
const endOfDay = new Date();
endOfDay.setHours(23, 59, 59, 999);

// Beginning of month
const firstOfMonth = new Date();
firstOfMonth.setDate(1);
firstOfMonth.setHours(0, 0, 0, 0);

// Days in month
const daysInMonth = new Date(2024, 2, 0).getDate();   // Feb 2024
console.log(daysInMonth);
// [ 29 ]

Leap year check:

function isLeapYear(year) {
  return new Date(year, 1, 29).getDate() === 29;
}

console.log(isLeapYear(2024));
// [ true ]
console.log(isLeapYear(2023));
// [ false ]

Date.parse and Date.UTC:

console.log(Date.parse('2024-01-15T10:30:00Z'));
// [ 1705314600000 ]

console.log(Date.UTC(2024, 0, 15, 10, 30, 0));
// [ 1705314600000 ]

Date.UTC returns a timestamp for the given UTC parts — useful for creating UTC dates:

const d = new Date(Date.UTC(2024, 0, 15));
console.log(d.toISOString());
// [ 2024-01-15T00:00:00.000Z ]

c – Common date patterns

These are the patterns you’ll use in real code — getting, formatting, comparing, and manipulating dates.

Pattern 1 — Get today’s date as YYYY-MM-DD:

function today() {
  const d = new Date();
  return d.toISOString().slice(0, 10);
}

console.log(today());
// [ '2024-01-15' ]

Pattern 2 — Format as YYYY-MM-DD HH:mm:ss:

function formatDate(d) {
  const pad = n => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` +
         `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
}

console.log(formatDate(new Date()));
// [ '2024-01-15 10:30:00' ]

Pattern 3 — Add days:

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

console.log(addDays(new Date('2024-01-15'), 10).toISOString().slice(0, 10));
// [ '2024-01-25' ]

Pattern 4 — Difference in days:

function daysBetween(a, b) {
  const msPerDay = 1000 * 60 * 60 * 24;
  const utcA = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
  const utcB = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
  return Math.floor((utcB - utcA) / msPerDay);
}

console.log(daysBetween(new Date('2024-01-15'), new Date('2024-01-20')));
// [ 5 ]

Using UTC avoids daylight saving time issues.

Pattern 5 — Check if same day:

function isSameDay(a, b) {
  return a.getFullYear() === b.getFullYear() &&
         a.getMonth() === b.getMonth() &&
         a.getDate() === b.getDate();
}

console.log(isSameDay(new Date('2024-01-15T10:00'), new Date('2024-01-15T22:00')));
// [ true ]

Pattern 6 — Check if date is today:

function isToday(d) {
  const today = new Date();
  return isSameDay(d, today);
}

Pattern 7 — Time ago / relative time:

function timeAgo(date) {
  const seconds = Math.floor((Date.now() - date.getTime()) / 1000);

  if (seconds < 60) return 'just now';
  if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes ago`;
  if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours ago`;
  return `${Math.floor(seconds / 86400)} days ago`;
}

console.log(timeAgo(new Date(Date.now() - 300000)));
// [ '5 minutes ago' ]

Pattern 8 — Intl.RelativeTimeFormat:

function relative(date) {
  const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
  const diffMs = date - Date.now();
  const diffSec = Math.round(diffMs / 1000);
  const diffMin = Math.round(diffSec / 60);
  const diffHour = Math.round(diffMin / 60);
  const diffDay = Math.round(diffHour / 24);

  if (Math.abs(diffSec) < 60) return rtf.format(diffSec, 'second');
  if (Math.abs(diffMin) < 60) return rtf.format(diffMin, 'minute');
  if (Math.abs(diffHour) < 24) return rtf.format(diffHour, 'hour');
  return rtf.format(diffDay, 'day');
}

Pattern 9 — Age from birthdate:

function age(birthdate) {
  const today = new Date();
  let age = today.getFullYear() - birthdate.getFullYear();
  const m = today.getMonth() - birthdate.getMonth();
  if (m < 0 || (m === 0 && today.getDate() < birthdate.getDate())) {
    age--;
  }
  return age;
}

Pattern 10 — ISO week number:

function isoWeek(d) {
  const date = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
  const dayNum = date.getUTCDay() || 7;
  date.setUTCDate(date.getUTCDate() + 4 - dayNum);
  const yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
  return Math.ceil(((date - yearStart) / 86400000 + 1) / 7);
}

Pattern 11 — Format with timezone:

const d = new Date();

console.log(d.toLocaleString('en-US', { timeZone: 'America/New_York' }));
// [ 1/15/2024, 5:30:00 AM ]

console.log(d.toLocaleString('en-US', { timeZone: 'Asia/Tokyo' }));
// [ 1/15/2024, 7:30:00 PM ]

Pattern 12 — Parse date safely:

function parseDate(str) {
  const d = new Date(str);
  if (isNaN(d.getTime())) {
    throw new Error(`Invalid date: ${str}`);
  }
  return d;
}

Always check for Invalid Date after parsing.

A complete date utility module:

const DateUtil = {
  today() {
    const d = new Date();
    d.setHours(0, 0, 0, 0);
    return d;
  },

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

  daysBetween(a, b) {
    const ms = 1000 * 60 * 60 * 24;
    const utcA = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
    const utcB = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
    return Math.floor((utcB - utcA) / ms);
  },

  format(d, pattern = 'YYYY-MM-DD') {
    const pad = n => String(n).padStart(2, '0');
    return pattern
      .replace('YYYY', d.getFullYear())
      .replace('MM', pad(d.getMonth() + 1))
      .replace('DD', pad(d.getDate()))
      .replace('HH', pad(d.getHours()))
      .replace('mm', pad(d.getMinutes()))
      .replace('ss', pad(d.getSeconds()));
  },

  isSameDay(a, b) {
    return a.getFullYear() === b.getFullYear() &&
           a.getMonth() === b.getMonth() &&
           a.getDate() === b.getDate();
  },

  startOfDay(d) {
    const r = new Date(d);
    r.setHours(0, 0, 0, 0);
    return r;
  },

  endOfDay(d) {
    const r = new Date(d);
    r.setHours(23, 59, 59, 999);
    return r;
  }
};

Date libraries — when native Date isn’t enough:

LibraryWhy use it
date-fnsFunctional, tree-shakeable, immutable
Day.jsTiny (2KB), Moment-compatible API
LuxonModern, immutable, timezone-aware
TemporalNew built-in proposal (stage 3)

The Temporal API is a much better date library being added to JavaScript itself. It fixes all the Date quirks — immutable objects, 1-indexed months, proper timezone handling, duration types. Until it’s widely available, libraries fill the gap.


Complete Example Session

// ============================================
// PART 1: CREATE A DATE
// ============================================

const now = new Date();
console.log(typeof now);
// [ 'object' ]

// ============================================
// PART 2: FROM STRING
// ============================================

const specific = new Date('2024-01-15T10:30:00');
console.log(specific.toISOString());
// [ '2024-01-15T10:30:00.000Z' ]

// ============================================
// PART 3: FROM PARTS
// ============================================

const fromParts = new Date(2024, 0, 15, 10, 30, 0);
console.log(fromParts.getFullYear());
// [ 2024 ]
console.log(fromParts.getMonth());
// [ 0 ]

// ============================================
// PART 4: TIMESTAMP
// ============================================

console.log(Date.now() > 0);
// [ true ]

// ============================================
// PART 5: GETTERS
// ============================================

const d = new Date('2024-01-15T10:30:45.123Z');

console.log(d.getUTCFullYear());
// [ 2024 ]
console.log(d.getUTCMonth());
// [ 0 ]
console.log(d.getUTCDate());
// [ 15 ]
console.log(d.getUTCDay());
// [ 1 ]
console.log(d.getUTCHours());
// [ 10 ]
console.log(d.getUTCMinutes());
// [ 30 ]
console.log(d.getUTCSeconds());
// [ 45 ]
console.log(d.getUTCMilliseconds());
// [ 123 ]

// ============================================
// PART 6: SETTERS
// ============================================

const d2 = new Date('2024-01-15');
d2.setFullYear(2025);
d2.setMonth(5);
d2.setDate(20);
console.log(d2.toISOString());
// [ '2025-06-20T00:00:00.000Z' ]

// ============================================
// PART 7: FORMATTING
// ============================================

const d3 = new Date('2024-01-15T10:30:00Z');

console.log(d3.toISOString());
// [ '2024-01-15T10:30:00.000Z' ]

console.log(d3.toDateString());
// [ 'Mon Jan 15 2024' ]

console.log(d3.toTimeString().slice(0, 8));
// [ '10:30:00' ]

// ============================================
// PART 8: LOCALE FORMATTING
// ============================================

console.log(d3.toLocaleDateString('en-US'));
// [ '1/15/2024' ]

console.log(d3.toLocaleDateString('en-GB'));
// [ '15/01/2024' ]

console.log(d3.toLocaleDateString('en-US', { weekday: 'long' }));
// [ 'Monday' ]

// ============================================
// PART 9: COMPARING
// ============================================

const a = new Date('2024-01-15');
const b = new Date('2024-06-20');

console.log(a < b);
// [ true ]

console.log(b - a);
// [ 13536000000 ]

// ============================================
// PART 10: DIFFERENCE IN DAYS
// ============================================

const diffMs = b - a;
const diffDays = diffMs / (1000 * 60 * 60 * 24);
console.log(diffDays);
// [ 156.66666666666666 ]

// ============================================
// PART 11: ADD DAYS
// ============================================

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

console.log(addDays(a, 7).toISOString().slice(0, 10));
// [ '2024-01-22' ]

// ============================================
// PART 12: INVALID DATE
// ============================================

const bad = new Date('not a date');
console.log(isNaN(bad));
// [ true ]

console.log(bad.toString());
// [ 'Invalid Date' ]

// ============================================
// PART 13: DATE.PARSE
// ============================================

console.log(Date.parse('2024-01-15T00:00:00Z'));
// [ 1705276800000 ]

// ============================================
// PART 14: DATE.UTC
// ============================================

console.log(Date.UTC(2024, 0, 15));
// [ 1705276800000 ]

// ============================================
// PART 15: ISO WEEK
// ============================================

function isoWeek(d) {
  const date = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
  const dayNum = date.getUTCDay() || 7;
  date.setUTCDate(date.getUTCDate() + 4 - dayNum);
  const yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
  return Math.ceil(((date - yearStart) / 86400000 + 1) / 7);
}

console.log(isoWeek(new Date('2024-01-15')));
// [ 3 ]

// ============================================
// PART 16: DAYS IN MONTH
// ============================================

console.log(new Date(2024, 2, 0).getDate());
// [ 29 ]

// ============================================
// PART 17: LEAP YEAR
// ============================================

function isLeapYear(year) {
  return new Date(year, 1, 29).getDate() === 29;
}

console.log(isLeapYear(2024));
// [ true ]

console.log(isLeapYear(2023));
// [ false ]

// ============================================
// PART 18: RELATIVE TIME
// ============================================

const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
console.log(rtf.format(-1, 'day'));
// [ 'yesterday' ]

console.log(rtf.format(2, 'hour'));
// [ 'in 2 hours' ]

// ============================================
// PART 19: TIMEZONE
// ============================================

const d4 = new Date('2024-01-15T10:30:00Z');
console.log(d4.toLocaleString('en-US', { timeZone: 'America/New_York' }));
// [ '1/15/2024, 5:30:00 AM' ]

// ============================================
// PART 20: FULL SCRIPT
// ============================================

const now48 = new Date();
console.log(now48);

const specific48 = new Date('2024-01-15T10:30:00');
console.log(specific48);

const fromParts48 = new Date(2024, 0, 15, 10, 30, 0);
console.log(fromParts48);

const timestamp48 = Date.now();
console.log(timestamp48);

console.log(now48.getFullYear());
console.log(now48.getMonth());
console.log(now48.getDate());
console.log(now48.getDay());
console.log(now48.getHours());
console.log(now48.getMinutes());
console.log(now48.getSeconds());
console.log(now48.getMilliseconds());
console.log(now48.getTime());

now48.setFullYear(2025);
now48.setMonth(5);
now48.setDate(20);

console.log(now48.toISOString());
console.log(now48.toDateString());
console.log(now48.toTimeString());
console.log(now48.toLocaleDateString());
console.log(now48.toLocaleTimeString());
console.log(now48.toLocaleString());

const d1_48 = new Date('2024-01-15');
const d2_48 = new Date('2024-06-20');
console.log(d2_48 - d1_48);

console.log(Date.parse('2024-01-15'));
console.log(Date.UTC(2024, 0, 15));

Quick Reference

Creating Dates

FormExample
Nownew Date()
Stringnew Date('2024-01-15')
ISOnew Date('2024-01-15T10:30:00Z')
Partsnew Date(2024, 0, 15, 10, 30)
Timestampnew Date(1705314600000)
Copynew Date(other)
Timestamp nowDate.now()
ParseDate.parse(str)
UTC partsDate.UTC(2024, 0, 15)

Date Parts

ArgMeaningRange
YearFull year
Month0-indexed0–11
DayDay1–31
Hours24h0–23
Minutes0–59
Seconds0–59
ms0–999

Getters

MethodReturns
getFullYear()Year
getMonth()0–11
getDate()1–31
getDay()0–6 (Sun=0)
getHours()0–23
getMinutes()0–59
getSeconds()0–59
getMilliseconds()0–999
getTime()Timestamp
getTimezoneOffset()Minutes from UTC
UTC variantsPrefixed getUTC...

Setters

MethodMeaning
setFullYear(y)Set year
setMonth(m)Set month
setDate(d)Set day
setHours(h)Set hours
setMinutes(m)Set minutes
setSeconds(s)Set seconds
setMilliseconds(ms)Set ms
setTime(ts)From timestamp

Formatting

MethodOutput
toISOString()2024-01-15T10:30:00.000Z
toString()Full local string
toDateString()Date part only
toTimeString()Time part only
toUTCString()RFC 1123 UTC
toLocaleString()Localized
toLocaleDateString()Localized date
toLocaleTimeString()Localized time
toJSON()Same as ISO

Locale Options

OptionValues
weekdaylong, short, narrow
yearnumeric, 2-digit
monthnumeric, 2-digit, long, short
daynumeric, 2-digit
hournumeric, 2-digit
minutenumeric, 2-digit
secondnumeric, 2-digit
hour12true, false
timeZone'UTC', 'America/New_York', etc.

Millisecond Units

Unitms
Second1000
Minute60000
Hour3600000
Day86400000
Week604800000

Common Operations

TaskCode
Today (midnight)d.setHours(0,0,0,0)
End of dayd.setHours(23,59,59,999)
Add daysd.setDate(d.getDate() + n)
Add monthsd.setMonth(d.getMonth() + n)
Add yearsd.setFullYear(d.getFullYear() + n)
Differenceb - a (ms)
Days between(b - a) / 86400000
Same dayCompare Y/M/D
Format ISO dated.toISOString().slice(0, 10)
Check validity!isNaN(d.getTime())

Libraries

LibraryNotes
date-fnsFunctional, tree-shakeable
Day.jsTiny, Moment-compatible
LuxonModern, immutable
TemporalBuilt-in (stage 3)

Best Practices

Do This:

// Use ISO 8601 strings for parsing
new Date('2024-01-15T10:30:00Z');               // ✅

// Use Date.now() for timestamps
const ts = Date.now();                          // ✅

// Copy dates before modifying
const next = new Date(d);
next.setDate(next.getDate() + 1);               // ✅

// Use UTC for date-only arithmetic
Date.UTC(y, m, d);                              // ✅

// Check for Invalid Date
if (isNaN(d.getTime())) { ... }                 // ✅

// Use toLocaleString for display
d.toLocaleDateString('en-US', { ... });         // ✅

// Use Intl.DateTimeFormat for reusable formatting
const fmt = new Intl.DateTimeFormat('en-US');   // ✅

// Remember month is 0-indexed
new Date(2024, 0, 15);                          // ✅ January

Don’t Do This:

// Don't trust string parsing
new Date('01/15/2024');                         // ⚠️  locale-dependent

// Don't use getYear()
d.getYear();                                    // ❌ deprecated (use getFullYear)

// Don't forget month is 0-indexed
new Date(2024, 1, 15);                          // ⚠️  February, not January

// Don't mutate dates unexpectedly
function addDay(d) {
  d.setDate(d.getDate() + 1);
  return d;                                     // ❌ mutates input
}

// Don't compare with ===
d1 === d2;                                      // ❌ reference comparison
d1.getTime() === d2.getTime();                  // ✅

// Don't compute days without UTC
(b - a) / 86400000;                             // ⚠️  DST issues

Common Pitfalls

PitfallProblemSolution
Month is 0-indexedOff-by-oneJan is 0
getYear() deprecatedWrong valuegetFullYear()
String parsing unreliableDifferent resultsISO 8601
Mutating datesSide effectsCopy first
=== on datesReference comparegetTime()
DST breaks diffsOff-by-one daysUse UTC
setMonth rolls overFeb 31 → Mar 2Known behavior
Timezone confusionOff hoursUse getUTC/setUTC
Date in JSONISO string onlyCustom serialize

Real-World Examples

1. Current Date

const now = new Date();
console.log(now.toISOString());
// [ '2024-01-15T10:30:00.000Z' ]

2. From String

const d = new Date('2024-01-15T10:30:00Z');
console.log(d.toISOString());
// [ '2024-01-15T10:30:00.000Z' ]

3. From Parts

const d = new Date(2024, 0, 15, 10, 30, 0);
console.log(d.getFullYear());
// [ 2024 ]

4. Timestamp

console.log(Date.now());
// [ 1705314600000 ]

5. Get Components

const d = new Date('2024-01-15T10:30:45Z');

console.log(d.getUTCFullYear());   // 2024
console.log(d.getUTCMonth());      // 0
console.log(d.getUTCDate());       // 15
console.log(d.getUTCHours());      // 10
console.log(d.getUTCMinutes());    // 30

6. Set Components

const d = new Date('2024-01-15');
d.setFullYear(2025);
d.setMonth(5);
d.setDate(20);
console.log(d.toISOString());
// [ '2025-06-20T00:00:00.000Z' ]

7. Format ISO

const d = new Date('2024-01-15T10:30:00Z');
console.log(d.toISOString());
// [ '2024-01-15T10:30:00.000Z' ]

8. Locale Date

const d = new Date('2024-01-15');
console.log(d.toLocaleDateString('en-US'));
// [ '1/15/2024' ]

console.log(d.toLocaleDateString('en-GB'));
// [ '15/01/2024' ]

9. Full Weekday

const d = new Date('2024-01-15');
console.log(d.toLocaleDateString('en-US', { weekday: 'long' }));
// [ 'Monday' ]

10. Compare Dates

const a = new Date('2024-01-15');
const b = new Date('2024-06-20');
console.log(a < b);
// [ true ]

11. Difference in Days

const a = new Date('2024-01-15');
const b = new Date('2024-01-20');
console.log((b - a) / 86400000);
// [ 5 ]

12. Add Days

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

console.log(addDays(new Date('2024-01-15'), 10).toISOString().slice(0, 10));
// [ '2024-01-25' ]

13. Same Day Check

function isSameDay(a, b) {
  return a.getFullYear() === b.getFullYear() &&
         a.getMonth() === b.getMonth() &&
         a.getDate() === b.getDate();
}

14. Start of Day

function startOfDay(d) {
  const r = new Date(d);
  r.setHours(0, 0, 0, 0);
  return r;
}

15. Days in Month

console.log(new Date(2024, 2, 0).getDate());
// [ 29 ]

16. Leap Year

function isLeapYear(year) {
  return new Date(year, 1, 29).getDate() === 29;
}

console.log(isLeapYear(2024));
// [ true ]

17. Relative Time

const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
console.log(rtf.format(-2, 'day'));
// [ '2 days ago' ]

18. Timezone Formatting

const d = new Date();
console.log(d.toLocaleString('en-US', { timeZone: 'Asia/Tokyo' }));

19. Validate

function isValidDate(d) {
  return d instanceof Date && !isNaN(d.getTime());
}

20. Full Script

const now48 = new Date();
console.log(now48);

const specific48 = new Date('2024-01-15T10:30:00');
console.log(specific48);

const fromParts48 = new Date(2024, 0, 15, 10, 30, 0);
console.log(fromParts48);

const timestamp48 = Date.now();
console.log(timestamp48);

console.log(now48.getFullYear());
console.log(now48.getMonth());
console.log(now48.getDate());
console.log(now48.getDay());
console.log(now48.getHours());
console.log(now48.getMinutes());
console.log(now48.getSeconds());
console.log(now48.getMilliseconds());
console.log(now48.getTime());

now48.setFullYear(2025);
now48.setMonth(5);
now48.setDate(20);

console.log(now48.toISOString());
console.log(now48.toDateString());
console.log(now48.toTimeString());
console.log(now48.toLocaleDateString());
console.log(now48.toLocaleTimeString());
console.log(now48.toLocaleString());

const d1_48 = new Date('2024-01-15');
const d2_48 = new Date('2024-06-20');
console.log(d2_48 - d1_48);

console.log(Date.parse('2024-01-15'));
console.log(Date.UTC(2024, 0, 15));

Visual: Date Internal Representation

┌──────────────────────────────────────────────┐
│  new Date('2024-01-15T10:30:00Z')            │
│                                              │
│  Stored internally:                          │
│  ┌─────────────────────────────────────┐     │
│  │ 1705314600000                       │     │
│  │ (milliseconds since 1970-01-01 UTC) │     │
│  └─────────────────────────────────────┘     │
│                                              │
│  Same instant, different views:              │
│                                              │
│  Local:  depends on your timezone            │
│  UTC:    2024-01-15T10:30:00.000Z            │
│  ISO:    "2024-01-15T10:30:00.000Z"          │
│  Epoch:  1705314600000                       │
│                                              │
└──────────────────────────────────────────────┘

Visual: Month is 0-Indexed

┌──────────────────────────────────────────────┐
│  Month index                                 │
│                                              │
│  new Date(2024, 0, 15)  → January 15         │
│  new Date(2024, 1, 15)  → February 15        │
│  new Date(2024, 2, 15)  → March 15           │
│  new Date(2024, 11, 15) → December 15        │
│                                              │
│  ⚠️  Off-by-one incoming!                    │
│                                              │
└──────────────────────────────────────────────┘

Visual: UTC vs Local

┌──────────────────────────────────────────────┐
│  Server timestamp: 1705314600000             │
│  (= 2024-01-15T10:30:00Z)                    │
│                                              │
│  Displayed in different zones:               │
│                                              │
│  UTC:             10:30                      │
│  America/New_York: 05:30                     │
│  Europe/London:    10:30                     │
│  Asia/Tokyo:       19:30                     │
│                                              │
│  Same instant, different display             │
│                                              │
└──────────────────────────────────────────────┘

Summary

ConceptSyntaxExample
Nownew Date()Current moment
From stringnew Date('2024-01-15')Parse ISO
From partsnew Date(2024, 0, 15)Month 0-indexed
From timestampnew Date(ms)Since epoch
TimestampDate.now()Milliseconds
ParseDate.parse(str)→ ms
UTC partsDate.UTC(...)→ ms
Get yeargetFullYear()2024
Get monthgetMonth()0–11
Get dategetDate()1–31
Get daygetDay()0–6
Set yearsetFullYear(y)Mutates
Set monthsetMonth(m)0-indexed
Set datesetDate(d)Day
ISO formattoISOString()2024-01-15T10:30:00.000Z
Local formattoLocaleString()Localized
Custom localetoLocaleString(locale, opts)Full control
Comparea < bWorks
Differenceb - aMilliseconds
Days between(b - a) / 86400000Number
Add daysd.setDate(d.getDate() + n)Mutates
Check valid!isNaN(d.getTime())Boolean
RelativeIntl.RelativeTimeFormat“2 days ago”

Key takeaways:

  • A Date is a single number — milliseconds since the Unix epoch
  • Month is 0-indexed — January is 0, December is 11
  • getDay() returns 0–6 with Sunday as 0
  • Date.now() is faster than new Date().getTime() — use it for timestamps
  • Dates are mutable — copy with new Date(d) before modifying
  • === compares references — use getTime() or comparison operators
  • - between dates gives milliseconds — divide by 86400000 for days
  • UTC avoids DST issues for date-only arithmetic
  • String parsing is unreliable — prefer ISO 8601 or Date parts
  • toISOString() is the safe, universal serialization format
  • toLocaleString() and Intl.DateTimeFormat handle display
  • Intl.RelativeTimeFormat gives “yesterday”, “in 2 hours”
  • Invalid Dates have NaN time — check with isNaN(d.getTime())
  • Modern code should consider Temporal or libraries like date-fns for complex work

Remember: Date is quirky but unavoidable. Store dates as UTC milliseconds internally, format them for display only at the edges. Remember the 0-indexed month. Copy before mutating. Compare with getTime() or -. Use toISOString for serialization and toLocaleString for humans. Guard against Invalid Date. Master these rules, and JavaScript dates stop being a trap — they become a predictable tool.


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!