Date and Time Handling

1. Date Object Creation and Methods

Creation Method Syntax Description Example
Current Date/Time new Date() Current date and time (local timezone) new Date()
From Timestamp new Date(milliseconds) Milliseconds since Unix epoch (Jan 1, 1970 UTC) new Date(0)
From String new Date(dateString) Parse date string; format varies (prefer ISO 8601) new Date('2024-01-15')
From Components new Date(year, month, ...) Year, month (0-11), day (1-31), hour, min, sec, ms new Date(2024, 0, 15)
Static Now Date.now() Current timestamp in milliseconds Date.now()
Copy Date new Date(date) Create new Date from existing Date object new Date(oldDate)
Getter Methods Returns UTC Equivalent Description
getFullYear() 4-digit year getUTCFullYear() 2024 (not 24!)
getMonth() 0-11 getUTCMonth() 0=Jan, 11=Dec
getDate() 1-31 getUTCDate() Day of month
getDay() 0-6 getUTCDay() 0=Sunday, 6=Saturday
getHours() 0-23 getUTCHours() Hour (24-hour format)
getMinutes() 0-59 getUTCMinutes() Minutes
getSeconds() 0-59 getUTCSeconds() Seconds
getMilliseconds() 0-999 getUTCMilliseconds() Milliseconds
getTime() Number - Timestamp (ms since epoch)
getTimezoneOffset() Minutes - Offset from UTC (negative for ahead)
Setter Methods Parameters UTC Equivalent Returns
setFullYear() year, [month], [day] setUTCFullYear() Timestamp
setMonth() month (0-11), [day] setUTCMonth() Timestamp
setDate() day (1-31) setUTCDate() Timestamp
setHours() hour, [min], [sec], [ms] setUTCHours() Timestamp
setMinutes() min, [sec], [ms] setUTCMinutes() Timestamp
setSeconds() sec, [ms] setUTCSeconds() Timestamp
setMilliseconds() ms (0-999) setUTCMilliseconds() Timestamp
setTime() timestamp - Timestamp

Example: Date creation and methods

// Current date/time
const now = new Date();
console.log(now); // e.g., "2024-01-15T10:30:45.123Z"

// From timestamp (ms since Jan 1, 1970 UTC)
const epoch = new Date(0); // "1970-01-01T00:00:00.000Z"
const timestamp = new Date(1705318245123);

// Current timestamp (faster than new Date().getTime())
Date.now(); // 1705318245123

// From ISO string (recommended format)
const isoDate = new Date('2024-01-15T10:30:00.000Z'); // UTC
const isoLocal = new Date('2024-01-15T10:30:00'); // local time
const dateOnly = new Date('2024-01-15'); // midnight UTC

// ⚠️ Date string parsing is implementation-dependent!
new Date('Jan 15, 2024'); // works but inconsistent
new Date('15 Jan 2024'); // may fail in some browsers
new Date('2024/01/15'); // works

// From components (month is 0-indexed!)
const date = new Date(2024, 0, 15); // Jan 15, 2024 (local time)
const fullDate = new Date(2024, 0, 15, 10, 30, 45, 123);
// Year, Month(0-11), Day, Hour, Min, Sec, Ms

// ⚠️ Month is 0-indexed (0=Jan, 11=Dec)
new Date(2024, 0, 15); // January 15
new Date(2024, 11, 25); // December 25

// Copy date
const original = new Date();
const copy = new Date(original);
copy.setDate(copy.getDate() + 1); // doesn't affect original

// Getter methods (local time)
const d = new Date('2024-01-15T10:30:45.123');
d.getFullYear(); // 2024 (NOT getYear()!)
d.getMonth(); // 0 (January, 0-indexed!)
d.getDate(); // 15 (day of month, 1-31)
d.getDay(); // 1 (Monday, 0=Sunday)
d.getHours(); // 10
d.getMinutes(); // 30
d.getSeconds(); // 45
d.getMilliseconds(); // 123
d.getTime(); // 1705318245123 (timestamp)

// Timezone offset
d.getTimezoneOffset(); // e.g., -300 (minutes, UTC-5)
// Negative means ahead of UTC (e.g., UTC+5 = -300)

// Setter methods (chainable via return value)
const date = new Date('2024-01-15');
date.setFullYear(2025); // 2025-01-15
date.setMonth(11); // December (0-indexed!)
date.setDate(25); // 2025-12-25
date.setHours(10, 30, 0, 0); // 10:30:00.000

// Setters return timestamp
const timestamp = date.setDate(20); // returns new timestamp

// Out-of-range values auto-adjust
date.setDate(32); // rolls to next month
date.setMonth(12); // rolls to next year (Jan)
date.setDate(0); // goes to last day of previous month

const feb = new Date(2024, 1, 30); // Feb 30 → Mar 1
const endOfMonth = new Date(2024, 2, 0); // Mar 0 → Feb 29

// Invalid dates
const invalid = new Date('invalid');
invalid.toString(); // "Invalid Date"
isNaN(invalid.getTime()); // true
invalid.getTime(); // NaN

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

// Compare dates
const d1 = new Date('2024-01-15');
const d2 = new Date('2024-01-20');

d1 < d2; // true
d1.getTime() < d2.getTime(); // true (more explicit)

// Equality requires .getTime()
d1 === d2; // false (different objects)
d1.getTime() === d2.getTime(); // false (different times)

const d3 = new Date('2024-01-15');
d1.getTime() === d3.getTime(); // true

// Date arithmetic (use timestamps)
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);

const nextWeek = new Date();
nextWeek.setDate(nextWeek.getDate() + 7);

// Common patterns
// Start of day
const startOfDay = new Date();
startOfDay.setHours(0, 0, 0, 0);

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

// Age calculation
function getAge(birthDate) {
    const today = new Date();
    let age = today.getFullYear() - birthDate.getFullYear();
    const monthDiff = today.getMonth() - birthDate.getMonth();
    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
        age--;
    }
    return age;
}
Warning: Month is 0-indexed (0=Jan, 11=Dec) but day is 1-indexed. Date string parsing varies by browser - use ISO 8601 format. getYear() is deprecated - use getFullYear().

2. Date Formatting and Parsing

Method Format Example Output Notes
toString() Full string "Mon Jan 15 2024 10:30:45 GMT-0500" Locale-dependent
toDateString() Date only "Mon Jan 15 2024" Human-readable
toTimeString() Time only "10:30:45 GMT-0500 (EST)" With timezone
toISOString() ISO 8601 UTC "2024-01-15T15:30:45.123Z" Standard, UTC only
toJSON() ISO 8601 UTC "2024-01-15T15:30:45.123Z" Same as toISOString()
toUTCString() UTC string "Mon, 15 Jan 2024 15:30:45 GMT" RFC-1123 format
toLocaleString() Locale format "1/15/2024, 10:30:45 AM" Locale-aware
toLocaleDateString() Locale date "1/15/2024" Date only, locale
toLocaleTimeString() Locale time "10:30:45 AM" Time only, locale
valueOf() Timestamp 1705318245123 Milliseconds since epoch
Parsing Function Input Returns Notes
Date.parse() Date string Timestamp (ms) or NaN Inconsistent across browsers
new Date(string) Date string Date object Uses Date.parse() internally
Date.UTC() Year, month, day, ... UTC timestamp Like constructor but UTC

Example: Date formatting and parsing

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

// String representations
date.toString();
// "Mon Jan 15 2024 05:30:45 GMT-0500 (EST)"

date.toDateString();
// "Mon Jan 15 2024"

date.toTimeString();
// "05:30:45 GMT-0500 (Eastern Standard Time)"

date.toISOString();
// "2024-01-15T10:30:45.123Z" (always UTC, Z suffix)

date.toJSON();
// "2024-01-15T10:30:45.123Z" (same as toISOString)

date.toUTCString();
// "Mon, 15 Jan 2024 10:30:45 GMT" (RFC-1123)

// Locale-aware formatting
date.toLocaleString('en-US');
// "1/15/2024, 5:30:45 AM"

date.toLocaleDateString('en-US');
// "1/15/2024"

date.toLocaleTimeString('en-US');
// "5:30:45 AM"

// Different locales
date.toLocaleString('en-GB');
// "15/01/2024, 05:30:45"

date.toLocaleString('de-DE');
// "15.1.2024, 05:30:45"

date.toLocaleString('ja-JP');
// "2024/1/15 5:30:45"

// Locale with options
date.toLocaleString('en-US', {
    weekday: 'long',
    year: 'numeric',
    month: 'long',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit'
});
// "Monday, January 15, 2024 at 05:30 AM"

// Custom formatting with options
date.toLocaleDateString('en-US', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit'
});
// "01/15/2024"

date.toLocaleDateString('en-US', {
    weekday: 'short',
    month: 'short',
    day: 'numeric'
});
// "Mon, Jan 15"

// Parsing strings
Date.parse('2024-01-15T10:30:45.123Z'); // 1705318245123
Date.parse('2024-01-15'); // midnight UTC
Date.parse('Jan 15, 2024'); // implementation-dependent ⚠️

// Check if parse succeeded
const timestamp = Date.parse('invalid');
if (isNaN(timestamp)) {
    console.log('Invalid date string');
}

// new Date() uses Date.parse()
new Date('2024-01-15T10:30:45.123Z');

// Date.UTC() - create UTC timestamp from components
const utcTimestamp = Date.UTC(2024, 0, 15, 10, 30, 45, 123);
// Same as new Date(2024, 0, 15, 10, 30, 45, 123) but UTC

const utcDate = new Date(Date.UTC(2024, 0, 15, 10, 30));

// Custom formatting (manual)
function formatDate(date) {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
}
formatDate(new Date()); // "2024-01-15"

function formatDateTime(date) {
    const dateStr = formatDate(date);
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');
    return `${dateStr} ${hours}:${minutes}:${seconds}`;
}

// Format with time zone
function formatWithTimezone(date) {
    const offset = -date.getTimezoneOffset();
    const sign = offset >= 0 ? '+' : '-';
    const hours = String(Math.floor(Math.abs(offset) / 60)).padStart(2, '0');
    const minutes = String(Math.abs(offset) % 60).padStart(2, '0');
    return `${formatDateTime(date)} GMT${sign}${hours}:${minutes}`;
}

// Relative time formatting
function getRelativeTime(date) {
    const now = new Date();
    const diffMs = now - date;
    const diffSec = Math.floor(diffMs / 1000);
    const diffMin = Math.floor(diffSec / 60);
    const diffHour = Math.floor(diffMin / 60);
    const diffDay = Math.floor(diffHour / 24);
    
    if (diffSec < 60) return `${diffSec} seconds ago`;
    if (diffMin < 60) return `${diffMin} minutes ago`;
    if (diffHour < 24) return `${diffHour} hours ago`;
    if (diffDay < 30) return `${diffDay} days ago`;
    return date.toLocaleDateString();
}

// ISO 8601 variants
const d = new Date();

// Local ISO (no Z)
function toLocalISOString(date) {
    const offset = -date.getTimezoneOffset();
    const sign = offset >= 0 ? '+' : '-';
    const pad = (n) => String(n).padStart(2, '0');
    
    return date.getFullYear() +
        '-' + pad(date.getMonth() + 1) +
        '-' + pad(date.getDate()) +
        'T' + pad(date.getHours()) +
        ':' + pad(date.getMinutes()) +
        ':' + pad(date.getSeconds()) +
        '.' + String(date.getMilliseconds()).padStart(3, '0') +
        sign + pad(Math.floor(Math.abs(offset) / 60)) +
        ':' + pad(Math.abs(offset) % 60);
}

// Common date formats
function formatters(date) {
    return {
        iso: date.toISOString(), // "2024-01-15T10:30:45.123Z"
        date: date.toLocaleDateString(), // "1/15/2024"
        time: date.toLocaleTimeString(), // "10:30:45 AM"
        short: date.toLocaleString('en-US', {
            month: 'short',
            day: 'numeric',
            year: 'numeric'
        }), // "Jan 15, 2024"
        long: date.toLocaleString('en-US', {
            weekday: 'long',
            month: 'long',
            day: 'numeric',
            year: 'numeric'
        }) // "Monday, January 15, 2024"
    };
}
Note: toISOString() always outputs UTC (Z suffix). Date.parse() is inconsistent - prefer ISO 8601 format. Use Intl.DateTimeFormat for advanced locale formatting.

3. Timezone Handling and UTC Operations

Concept Method/Approach Description Example
Local Time get*() methods Methods without UTC prefix use local timezone date.getHours()
UTC Time getUTC*() methods Methods with UTC prefix use UTC timezone date.getUTCHours()
Timezone Offset getTimezoneOffset() Minutes difference from UTC (negative = ahead) -300 for UTC-5
UTC Constructor Date.UTC(y, m, d, ...) Create timestamp from UTC components Date.UTC(2024, 0, 15)
UTC String toISOString() Always returns UTC time with Z suffix "2024-01-15T10:30:45.123Z"
Timezone Name Intl.DateTimeFormat Get timezone identifier "America/New_York"

Example: Timezone handling

// Create date in local timezone
const local = new Date('2024-01-15T10:30:00'); // local 10:30

// Create date in UTC (Z suffix)
const utc = new Date('2024-01-15T10:30:00Z'); // UTC 10:30

// Local vs UTC getters
const date = new Date('2024-01-15T10:30:00Z');

// Local time (depends on system timezone)
date.getHours(); // e.g., 5 (if UTC-5)
date.getMinutes(); // 30

// UTC time (always same regardless of timezone)
date.getUTCHours(); // 10
date.getUTCMinutes(); // 30

// Timezone offset (minutes from UTC)
date.getTimezoneOffset();
// -300 for UTC-5 (EST) - negative means behind UTC
// 0 for UTC
// 60 for UTC+1 (CET)

// Convert offset to hours
const offsetHours = -date.getTimezoneOffset() / 60;
// -5 for EST, 0 for UTC, +1 for CET

// Get timezone name (modern browsers)
const timezoneName = Intl.DateTimeFormat().resolvedOptions().timeZone;
// "America/New_York", "Europe/London", "Asia/Tokyo"

// UTC constructor
const utcTimestamp = Date.UTC(2024, 0, 15, 10, 30, 0);
const utcDate = new Date(utcTimestamp);

// Difference: local vs UTC constructor
const localDate = new Date(2024, 0, 15, 10, 30); // 10:30 local
const utcDate2 = new Date(Date.UTC(2024, 0, 15, 10, 30)); // 10:30 UTC

localDate.getTime() !== utcDate2.getTime(); // true (different times!)

// Convert local to UTC
function toUTC(date) {
    return new Date(date.getTime() + date.getTimezoneOffset() * 60000);
}

// Convert UTC to local
function toLocal(date) {
    return new Date(date.getTime() - date.getTimezoneOffset() * 60000);
}

// Get UTC date at midnight
function getUTCDate(date) {
    return new Date(Date.UTC(
        date.getUTCFullYear(),
        date.getUTCMonth(),
        date.getUTCDate()
    ));
}

// Get local date at midnight
function getLocalDate(date) {
    return new Date(
        date.getFullYear(),
        date.getMonth(),
        date.getDate()
    );
}

// Compare dates ignoring time
function isSameDay(date1, date2) {
    return date1.getFullYear() === date2.getFullYear() &&
           date1.getMonth() === date2.getMonth() &&
           date1.getDate() === date2.getDate();
}

// Compare UTC dates
function isSameUTCDay(date1, date2) {
    return date1.getUTCFullYear() === date2.getUTCFullYear() &&
           date1.getUTCMonth() === date2.getUTCMonth() &&
           date1.getUTCDate() === date2.getUTCDate();
}

// Format with timezone
function formatWithTZ(date) {
    const offset = -date.getTimezoneOffset();
    const sign = offset >= 0 ? '+' : '-';
    const hours = String(Math.floor(Math.abs(offset) / 60)).padStart(2, '0');
    const minutes = String(Math.abs(offset) % 60).padStart(2, '0');
    
    return date.toISOString().slice(0, -1) + // remove Z
           `${sign}${hours}:${minutes}`;
}

// Parse ISO with timezone
const withTZ = new Date('2024-01-15T10:30:00+05:30'); // India
const withUTC = new Date('2024-01-15T10:30:00Z'); // UTC

withTZ.getTime() !== withUTC.getTime(); // different times

// Daylight Saving Time (DST) detection
function isDST(date) {
    const jan = new Date(date.getFullYear(), 0, 1);
    const jul = new Date(date.getFullYear(), 6, 1);
    const stdOffset = Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
    return date.getTimezoneOffset() < stdOffset;
}

isDST(new Date('2024-01-15')); // false (winter)
isDST(new Date('2024-07-15')); // true (summer, in DST zones)

// Working with specific timezones (use Intl)
const nyDate = new Date('2024-01-15T10:30:00Z');

const formatter = new Intl.DateTimeFormat('en-US', {
    timeZone: 'America/New_York',
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false
});

formatter.format(nyDate); // "01/15/2024, 05:30:00" (EST)

// Different timezone
const tokyoFormatter = new Intl.DateTimeFormat('en-US', {
    timeZone: 'Asia/Tokyo',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false
});

tokyoFormatter.format(nyDate); // "19:30" (JST, +9 hours)

// Get time in specific timezone
function getTimeInTimezone(date, timezone) {
    return new Intl.DateTimeFormat('en-US', {
        timeZone: timezone,
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hour12: false
    }).format(date);
}

getTimeInTimezone(new Date(), 'America/Los_Angeles');
getTimeInTimezone(new Date(), 'Europe/London');
getTimeInTimezone(new Date(), 'Asia/Dubai');

// Best practices
// 1. Store dates as UTC timestamps
const stored = date.getTime(); // or date.toISOString()

// 2. Convert to local for display
const displayed = new Date(stored);

// 3. Always use UTC for date comparisons
const isAfter = date1.getTime() > date2.getTime();

// 4. Use libraries for complex timezone work
// moment-timezone, date-fns-tz, luxon
Warning: Timezone offset is negative when ahead of UTC (UTC-5 = -300 minutes). DST changes offset during year. Always store dates as UTC timestamps. Date string without timezone = local time (implementation-dependent).

4. Date Arithmetic and Calculations

Operation Method Description Example
Add Days setDate(getDate() + n) Add/subtract days; auto-handles month/year rollover date.setDate(date.getDate() + 7)
Add Months setMonth(getMonth() + n) Add/subtract months; handles year rollover date.setMonth(date.getMonth() + 3)
Add Years setFullYear(getFullYear() + n) Add/subtract years date.setFullYear(date.getFullYear() + 1)
Add Hours setHours(getHours() + n) Add/subtract hours; handles day rollover date.setHours(date.getHours() + 24)
Add Milliseconds setTime(getTime() + ms) Precise time arithmetic using timestamps date.setTime(date.getTime() + 1000)
Date Difference date1 - date2 Subtract dates to get milliseconds difference diff = date1 - date2
Days Between (date1 - date2) / MS_PER_DAY Convert millisecond difference to days Math.floor(diff / 86400000)
Compare Dates date1 < date2 Direct comparison operators work if (date1 < date2) {...}

Example: Date arithmetic

// Add/subtract days
const today = new Date('2024-01-15');

const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1); // Jan 16

const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1); // Jan 14

const nextWeek = new Date(today);
nextWeek.setDate(nextWeek.getDate() + 7); // Jan 22

// Handles month/year rollover automatically
const endOfMonth = new Date('2024-01-31');
endOfMonth.setDate(endOfMonth.getDate() + 1); // Feb 1, 2024

// Add months
const date = new Date('2024-01-15');
date.setMonth(date.getMonth() + 1); // Feb 15, 2024
date.setMonth(date.getMonth() + 12); // Feb 15, 2025

// Month rollover edge case
const jan31 = new Date('2024-01-31');
jan31.setMonth(jan31.getMonth() + 1); // Feb 29 or Mar 2/3 (Feb has fewer days)

// Safe month addition (preserve day if possible)
function addMonths(date, months) {
    const d = new Date(date);
    const targetMonth = d.getMonth() + months;
    const targetYear = d.getFullYear() + Math.floor(targetMonth / 12);
    const finalMonth = ((targetMonth % 12) + 12) % 12;
    
    d.setFullYear(targetYear);
    d.setMonth(finalMonth);
    
    // If day changed (e.g., Jan 31 + 1 month), go to last day of month
    if (d.getDate() !== date.getDate()) {
        d.setDate(0); // Last day of previous month
    }
    return d;
}

// Add years
const now = new Date();
const nextYear = new Date(now);
nextYear.setFullYear(nextYear.getFullYear() + 1);

// Add hours
const hour = new Date();
const nextHour = new Date(hour);
nextHour.setHours(nextHour.getHours() + 1);

// Add minutes
const minute = new Date();
const nextMinute = new Date(minute);
nextMinute.setMinutes(nextMinute.getMinutes() + 30);

// Precise arithmetic with timestamps
const MS_PER_SECOND = 1000;
const MS_PER_MINUTE = 60 * 1000;
const MS_PER_HOUR = 60 * 60 * 1000;
const MS_PER_DAY = 24 * 60 * 60 * 1000;

// Add 7 days using timestamps
const d = new Date();
d.setTime(d.getTime() + 7 * MS_PER_DAY);

// Alternative using Date constructor
const future = new Date(Date.now() + 7 * MS_PER_DAY);

// Date difference (returns milliseconds)
const date1 = new Date('2024-01-20');
const date2 = new Date('2024-01-15');
const diffMs = date1 - date2; // 432000000 ms (5 days)

// Convert to different units
const diffSeconds = diffMs / 1000;
const diffMinutes = diffMs / (1000 * 60);
const diffHours = diffMs / (1000 * 60 * 60);
const diffDays = diffMs / (1000 * 60 * 60 * 24);

// Days between dates (whole days)
function daysBetween(date1, date2) {
    const MS_PER_DAY = 24 * 60 * 60 * 1000;
    const utc1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate());
    const utc2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate());
    return Math.floor((utc1 - utc2) / MS_PER_DAY);
}

daysBetween(new Date('2024-01-20'), new Date('2024-01-15')); // 5

// Compare dates
date1 < date2; // false
date1 > date2; // true
date1 === date2; // false (different objects)
date1.getTime() === date2.getTime(); // false (different times)

// Check if same day
function isSameDay(d1, d2) {
    return d1.getFullYear() === d2.getFullYear() &&
           d1.getMonth() === d2.getMonth() &&
           d1.getDate() === d2.getDate();
}

// Business days calculation (excluding weekends)
function addBusinessDays(date, days) {
    const result = new Date(date);
    let added = 0;
    
    while (added < days) {
        result.setDate(result.getDate() + 1);
        const day = result.getDay();
        if (day !== 0 && day !== 6) { // Not Sunday or Saturday
            added++;
        }
    }
    return result;
}

// Count business days between dates
function businessDaysBetween(startDate, endDate) {
    let count = 0;
    const current = new Date(startDate);
    
    while (current < endDate) {
        const day = current.getDay();
        if (day !== 0 && day !== 6) {
            count++;
        }
        current.setDate(current.getDate() + 1);
    }
    return count;
}

// Age calculation
function calculateAge(birthDate, asOfDate = new Date()) {
    let age = asOfDate.getFullYear() - birthDate.getFullYear();
    const monthDiff = asOfDate.getMonth() - birthDate.getMonth();
    
    if (monthDiff < 0 || (monthDiff === 0 && asOfDate.getDate() < birthDate.getDate())) {
        age--;
    }
    return age;
}

calculateAge(new Date('1990-05-15')); // e.g., 34

// Start/end of period
function startOfDay(date) {
    const d = new Date(date);
    d.setHours(0, 0, 0, 0);
    return d;
}

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

function startOfMonth(date) {
    return new Date(date.getFullYear(), date.getMonth(), 1);
}

function endOfMonth(date) {
    return new Date(date.getFullYear(), date.getMonth() + 1, 0);
}

function startOfYear(date) {
    return new Date(date.getFullYear(), 0, 1);
}

function endOfYear(date) {
    return new Date(date.getFullYear(), 11, 31, 23, 59, 59, 999);
}

// Days in month
function daysInMonth(date) {
    return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
}

daysInMonth(new Date('2024-02-01')); // 29 (leap year)
daysInMonth(new Date('2023-02-01')); // 28

// Is leap year
function isLeapYear(year) {
    return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}

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

// Elapsed time
function timeElapsed(startDate, endDate = new Date()) {
    const diff = endDate - startDate;
    
    const days = Math.floor(diff / MS_PER_DAY);
    const hours = Math.floor((diff % MS_PER_DAY) / MS_PER_HOUR);
    const minutes = Math.floor((diff % MS_PER_HOUR) / MS_PER_MINUTE);
    const seconds = Math.floor((diff % MS_PER_MINUTE) / MS_PER_SECOND);
    
    return {days, hours, minutes, seconds};
}

// Countdown timer
function countdown(targetDate) {
    const now = new Date();
    const diff = targetDate - now;
    
    if (diff <= 0) return {expired: true};
    
    return {
        expired: false,
        days: Math.floor(diff / MS_PER_DAY),
        hours: Math.floor((diff % MS_PER_DAY) / MS_PER_HOUR),
        minutes: Math.floor((diff % MS_PER_HOUR) / MS_PER_MINUTE),
        seconds: Math.floor((diff % MS_PER_MINUTE) / MS_PER_SECOND)
    };
}
Note: Date methods auto-adjust for overflow (e.g., Feb 30 → Mar 2). Use timestamps for precise arithmetic. Subtraction returns milliseconds. Month edge cases need careful handling (Jan 31 + 1 month).

5. Internationalization Date Formatting

Intl.DateTimeFormat Option Values Description Example Output
dateStyle full, long, medium, short Preset date format style "Monday, January 15, 2024"
timeStyle full, long, medium, short Preset time format style "10:30:45 AM EST"
weekday narrow, short, long Day of week name "M", "Mon", "Monday"
year numeric, 2-digit Year format "2024", "24"
month numeric, 2-digit, narrow, short, long Month format "1", "01", "J", "Jan", "January"
day numeric, 2-digit Day of month "15", "15"
hour numeric, 2-digit Hour format "10", "10"
minute numeric, 2-digit Minute format "30", "30"
second numeric, 2-digit Second format "45", "45"
timeZone IANA timezone identifier Display in specific timezone "America/New_York"
timeZoneName short, long, shortOffset, longOffset Timezone display "EST", "Eastern Standard Time"
hour12 true, false 12 or 24 hour format "10:30 AM" vs "10:30"

Example: Intl.DateTimeFormat usage

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

// Basic formatting
const formatter = new Intl.DateTimeFormat('en-US');
formatter.format(date); // "1/15/2024"

// Different locales
new Intl.DateTimeFormat('en-US').format(date); // "1/15/2024"
new Intl.DateTimeFormat('en-GB').format(date); // "15/01/2024"
new Intl.DateTimeFormat('de-DE').format(date); // "15.1.2024"
new Intl.DateTimeFormat('ja-JP').format(date); // "2024/1/15"
new Intl.DateTimeFormat('ar-EG').format(date); // "١٥‏/١‏/٢٠٢٤"

// Date and time styles
new Intl.DateTimeFormat('en-US', {
    dateStyle: 'full'
}).format(date);
// "Monday, January 15, 2024"

new Intl.DateTimeFormat('en-US', {
    dateStyle: 'long'
}).format(date);
// "January 15, 2024"

new Intl.DateTimeFormat('en-US', {
    dateStyle: 'medium'
}).format(date);
// "Jan 15, 2024"

new Intl.DateTimeFormat('en-US', {
    dateStyle: 'short'
}).format(date);
// "1/15/24"

new Intl.DateTimeFormat('en-US', {
    timeStyle: 'full'
}).format(date);
// "5:30:45 AM Eastern Standard Time"

new Intl.DateTimeFormat('en-US', {
    timeStyle: 'long'
}).format(date);
// "5:30:45 AM EST"

new Intl.DateTimeFormat('en-US', {
    timeStyle: 'medium'
}).format(date);
// "5:30:45 AM"

new Intl.DateTimeFormat('en-US', {
    timeStyle: 'short'
}).format(date);
// "5:30 AM"

// Combined date and time
new Intl.DateTimeFormat('en-US', {
    dateStyle: 'long',
    timeStyle: 'short'
}).format(date);
// "January 15, 2024 at 5:30 AM"

// Custom options
new Intl.DateTimeFormat('en-US', {
    weekday: 'long',
    year: 'numeric',
    month: 'long',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit'
}).format(date);
// "Monday, January 15, 2024, 05:30 AM"

// Weekday formats
new Intl.DateTimeFormat('en-US', {weekday: 'narrow'}).format(date); // "M"
new Intl.DateTimeFormat('en-US', {weekday: 'short'}).format(date); // "Mon"
new Intl.DateTimeFormat('en-US', {weekday: 'long'}).format(date); // "Monday"

// Month formats
new Intl.DateTimeFormat('en-US', {month: 'numeric'}).format(date); // "1"
new Intl.DateTimeFormat('en-US', {month: '2-digit'}).format(date); // "01"
new Intl.DateTimeFormat('en-US', {month: 'narrow'}).format(date); // "J"
new Intl.DateTimeFormat('en-US', {month: 'short'}).format(date); // "Jan"
new Intl.DateTimeFormat('en-US', {month: 'long'}).format(date); // "January"

// 12 vs 24 hour
new Intl.DateTimeFormat('en-US', {
    hour: '2-digit',
    minute: '2-digit',
    hour12: true
}).format(date);
// "05:30 AM"

new Intl.DateTimeFormat('en-US', {
    hour: '2-digit',
    minute: '2-digit',
    hour12: false
}).format(date);
// "05:30"

// Timezone handling
new Intl.DateTimeFormat('en-US', {
    timeZone: 'America/New_York',
    dateStyle: 'full',
    timeStyle: 'full'
}).format(date);
// "Monday, January 15, 2024 at 5:30:45 AM Eastern Standard Time"

new Intl.DateTimeFormat('en-US', {
    timeZone: 'Asia/Tokyo',
    dateStyle: 'full',
    timeStyle: 'full'
}).format(date);
// "Monday, January 15, 2024 at 7:30:45 PM Japan Standard Time"

new Intl.DateTimeFormat('en-US', {
    timeZone: 'Europe/London',
    dateStyle: 'long',
    timeStyle: 'long'
}).format(date);
// "January 15, 2024 at 10:30:45 AM GMT"

// Timezone name formats
new Intl.DateTimeFormat('en-US', {
    timeZone: 'America/New_York',
    timeZoneName: 'short'
}).format(date);
// "1/15/2024, EST"

new Intl.DateTimeFormat('en-US', {
    timeZone: 'America/New_York',
    timeZoneName: 'long'
}).format(date);
// "1/15/2024, Eastern Standard Time"

// Format parts (advanced)
const parts = new Intl.DateTimeFormat('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
}).formatToParts(date);

// [{type: 'month', value: 'January'}, {type: 'literal', value: ' '}, ...]

// Custom formatting using parts
function customFormat(date) {
    const parts = new Intl.DateTimeFormat('en-US', {
        year: 'numeric',
        month: 'long',
        day: 'numeric'
    }).formatToParts(date);
    
    const obj = {};
    parts.forEach(({type, value}) => {
        obj[type] = value;
    });
    
    return `${obj.day} of ${obj.month}, ${obj.year}`;
}
customFormat(date); // "15 of January, 2024"

// Format range (multiple dates)
const start = new Date('2024-01-15');
const end = new Date('2024-01-20');

new Intl.DateTimeFormat('en-US', {
    dateStyle: 'long'
}).formatRange(start, end);
// "January 15 – 20, 2024"

// Range across months
const start2 = new Date('2024-01-28');
const end2 = new Date('2024-02-05');

new Intl.DateTimeFormat('en-US', {
    dateStyle: 'long'
}).formatRange(start2, end2);
// "January 28 – February 5, 2024"

// Relative time formatting
const rtf = new Intl.RelativeTimeFormat('en-US', {numeric: 'auto'});

rtf.format(-1, 'day'); // "yesterday"
rtf.format(0, 'day'); // "today"
rtf.format(1, 'day'); // "tomorrow"
rtf.format(2, 'day'); // "in 2 days"
rtf.format(-2, 'week'); // "2 weeks ago"
rtf.format(3, 'month'); // "in 3 months"

// Numeric style
const rtfNumeric = new Intl.RelativeTimeFormat('en-US', {numeric: 'always'});
rtfNumeric.format(-1, 'day'); // "1 day ago" (not "yesterday")
rtfNumeric.format(0, 'day'); // "in 0 days" (not "today")

// Get relative time
function getRelativeTime(date) {
    const now = new Date();
    const diff = date - now;
    const absDiff = Math.abs(diff);
    
    const rtf = new Intl.RelativeTimeFormat('en-US', {numeric: 'auto'});
    
    if (absDiff < 60 * 1000) {
        return rtf.format(Math.round(diff / 1000), 'second');
    }
    if (absDiff < 60 * 60 * 1000) {
        return rtf.format(Math.round(diff / (60 * 1000)), 'minute');
    }
    if (absDiff < 24 * 60 * 60 * 1000) {
        return rtf.format(Math.round(diff / (60 * 60 * 1000)), 'hour');
    }
    if (absDiff < 30 * 24 * 60 * 60 * 1000) {
        return rtf.format(Math.round(diff / (24 * 60 * 60 * 1000)), 'day');
    }
    return rtf.format(Math.round(diff / (30 * 24 * 60 * 60 * 1000)), 'month');
}

// Reusable formatter
const dateFormatter = new Intl.DateTimeFormat('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
});

dateFormatter.format(date1);
dateFormatter.format(date2);
dateFormatter.format(date3);

// Get supported locales
Intl.DateTimeFormat.supportedLocalesOf(['en-US', 'de-DE', 'ja-JP']);
// ['en-US', 'de-DE', 'ja-JP']
Note: Intl.DateTimeFormat is locale-aware and timezone-aware. Use formatRange() for date ranges. Intl.RelativeTimeFormat for "2 days ago" style. Reuse formatters for performance.

Section 13 Summary

  • Creation: new Date() current; from timestamp/string/components; month is 0-indexed (0=Jan); use ISO 8601 for consistency; Date.now() for timestamp
  • Getters/Setters: get*/set* local time; getUTC*/setUTC* UTC; getTime() timestamp; setters auto-adjust overflow; getTimezoneOffset() minutes from UTC (negative = ahead)
  • Formatting: toISOString() UTC standard; toLocaleString() locale-aware; toString() local; toJSON() serialization; formatToParts() for custom formats
  • Timezones: Local vs UTC methods; offset in minutes; store as UTC timestamps; display in local; Intl.DateTimeFormat with timeZone option; DST affects offset
  • Arithmetic: setDate/Month/Year auto-rollover; timestamp math for precision; subtract dates = milliseconds; convert using MS_PER_DAY; daysBetween() use UTC dates
  • Intl.DateTimeFormat: Locale-aware formatting; dateStyle/timeStyle presets; custom options (weekday/month/year); timeZone for specific zones; formatRange() for periods; reuse formatters
  • Best practices: Store UTC timestamps; display in local; use ISO 8601; handle DST; beware month edge cases (Jan 31+1mo); use libraries (date-fns, luxon) for complex operations