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.DateTimeFormatwithtimeZoneoption; DST affects offset - Arithmetic:
setDate/Month/Yearauto-rollover; timestamp math for precision; subtract dates = milliseconds; convert using MS_PER_DAY;daysBetween()use UTC dates - Intl.DateTimeFormat: Locale-aware formatting;
dateStyle/timeStylepresets; custom options (weekday/month/year);timeZonefor 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