Mastering JavaScript Date Manipulation
Working with dates in JavaScript can be challenging due to various edge cases, time zones, and formatting requirements. This comprehensive guide will walk you through common date-related problems and their solutions, complete with practical examples and best practices.
Table of Contents
Basic Date Operations
Creating Date Objects
// Current date and time
const now = new Date();
// Specific date and time
const specificDate = new Date(2024, 11, 25, 12, 30, 0); // December 25, 2024, 12:30:00
// From ISO string
const fromISOString = new Date('2024-12-25T12:30:00Z');
// Unix timestamp (milliseconds)
const fromTimestamp = new Date(1703506200000);
Adding and Subtracting Time
function addDays(date, days) {
const result = new Date(date);
.setDate(date.getDate() + days);
resultreturn result;
}
function subtractMonths(date, months) {
const result = new Date(date);
.setMonth(date.getMonth() - months);
resultreturn result;
}
// Examples
const today = new Date();
const nextWeek = addDays(today, 7);
const threeMonthsAgo = subtractMonths(today, 3);
// Adding hours, minutes, seconds
function addTime(date, hours = 0, minutes = 0, seconds = 0) {
return new Date(date.getTime() +
* 60 * 60 * 1000) +
(hours * 60 * 1000) +
(minutes * 1000)
(seconds ;
) }
Commonly used Date methods
// Getting Components
.getFullYear() // Get year (4 digits)
date.getMonth() // Get month (0-11)
date.getDate() // Get day of month (1-31)
date.getDay() // Get day of week (0-6)
date.getHours() // Get hours (0-23)
date.getMinutes() // Get minutes (0-59)
date.getSeconds() // Get seconds (0-59)
date.getMilliseconds() // Get milliseconds (0-999)
date.getTime() // Get timestamp (milliseconds since epoch)
date
// Setting Components
.setFullYear() // Set year
date.setMonth() // Set month
date.setDate() // Set day of month
date.setHours() // Set hours
date.setMinutes() // Set minutes
date.setSeconds() // Set seconds
date.setMilliseconds() // Set milliseconds
date.setTime() // Set timestamp
date
// Conversion Methods
.toISOString() // Convert to ISO string
date.toString() // Convert to string
date.toLocaleString() // Convert to locale string
date.toLocaleDateString() // Convert to locale date
date.toLocaleTimeString() // Convert to locale time
date.toDateString() // Convert to date string
date.toTimeString() // Convert to time string
date.toUTCString() // Convert to UTC string
date
// Static Methods
Date.now() // Current timestamp
Date.parse() // Parse date string
Date.UTC() // Get UTC timestamp
Date Formatting and Parsing
Custom Date Formatting
function formatDate(date, format = 'YYYY-MM-DD') {
const pad = (num) => String(num).padStart(2, '0');
const formats = {
YYYY: date.getFullYear(),
MM: pad(date.getMonth() + 1),
DD: pad(date.getDate()),
HH: pad(date.getHours()),
mm: pad(date.getMinutes()),
ss: pad(date.getSeconds())
;
}
return format.replace(/YYYY|MM|DD|HH|mm|ss/g, match => formats[match]);
}
// Examples
const date = new Date('2024-12-25T14:30:00');
console.log(formatDate(date)); // "2024-12-25"
console.log(formatDate(date, 'DD/MM/YYYY')); // "25/12/2024"
console.log(formatDate(date, 'YYYY-MM-DD HH:mm')); // "2024-12-25 14:30"
Parsing Different Date Formats
function parseDate(dateString) {
// Try different date formats
const formats = [
// ISO format
/^\d{4}-\d{2}-\d{2}$/,
// DD/MM/YYYY
/^(\d{2})\/(\d{2})\/(\d{4})$/,
// MM-DD-YYYY
/^(\d{2})-(\d{2})-(\d{4})$/
;
]
for (const format of formats) {
if (format.test(dateString)) {
const parts = dateString.match(format);
if (format === formats[0]) {
return new Date(dateString);
else {
} // Rearrange parts based on format
const [_, first, second, year] = parts;
if (format === formats[1]) {
return new Date(`${year}-${second}-${first}`);
else {
} return new Date(`${year}-${first}-${second}`);
}
}
}
}
throw new Error('Invalid date format');
}
// Examples
console.log(parseDate('2024-12-25')); // ISO format
console.log(parseDate('25/12/2024')); // DD/MM/YYYY
console.log(parseDate('12-25-2024')); // MM-DD-YYYY
Date Comparisons and Validations
Date Comparison Functions
function isSameDay(date1, date2) {
return date1.getFullYear() === date2.getFullYear() &&
.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate();
date1
}
function isWeekend(date) {
const day = date.getDay();
return day === 0 || day === 6;
}
function getDaysBetween(date1, date2) {
const oneDay = 24 * 60 * 60 * 1000; // milliseconds in one day
const diffTime = Math.abs(date2 - date1);
return Math.round(diffTime / oneDay);
}
function isDateInRange(date, startDate, endDate) {
return date >= startDate && date <= endDate;
}
// Examples
const today = new Date();
const tomorrow = addDays(today, 1);
console.log(isSameDay(today, tomorrow)); // false
console.log(isWeekend(new Date('2024-12-28'))); // true (Saturday)
console.log(getDaysBetween(new Date('2024-01-01'), new Date('2024-12-31'))); // 365
Working with Time Zones
Time Zone Conversions
function convertToTimeZone(date, timeZone) {
return new Date(date.toLocaleString('en-US', {
timeZone: timeZone
;
}))
}
function getTimeZoneOffset(timeZone) {
const timeZoneDate = new Date().toLocaleString('en-US', {
,
timeZonetimeZoneName: 'short'
;
})return timeZoneDate.split(' ').pop();
}
// Examples
const nyDate = convertToTimeZone(new Date(), 'America/New_York');
const tokyoDate = convertToTimeZone(new Date(), 'Asia/Tokyo');
console.log(getTimeZoneOffset('America/New_York')); // EDT or EST
Date Ranges and Intervals
Working with Date Ranges
function generateDateRange(startDate, endDate) {
const dates = [];
let currentDate = new Date(startDate);
while (currentDate <= endDate) {
.push(new Date(currentDate));
dates.setDate(currentDate.getDate() + 1);
currentDate
}
return dates;
}
function getOverlappingDates(range1Start, range1End, range2Start, range2End) {
const start = new Date(Math.max(range1Start, range2Start));
const end = new Date(Math.min(range1End, range2End));
return start <= end ? { start, end } : null;
}
// Example
const dateRange = generateDateRange(
new Date('2024-12-24'),
new Date('2024-12-26')
;
)console.log(dateRange); // Array of dates from Dec 24-26
Business Date Calculations
Working with Business Days
function isBusinessDay(date) {
// Check if it's not a weekend
if (isWeekend(date)) return false;
// Example holidays (US)
const holidays = [
'2024-01-01', // New Year's Day
'2024-01-15', // Martin Luther King Jr. Day
'2024-02-19', // Presidents' Day
'2024-05-27', // Memorial Day
'2024-07-04', // Independence Day
'2024-09-02', // Labor Day
'2024-11-28', // Thanksgiving Day
'2024-12-25', // Christmas Day
;
]
return !holidays.includes(formatDate(date));
}
function addBusinessDays(date, days) {
let currentDate = new Date(date);
let remainingDays = days;
while (remainingDays > 0) {
.setDate(currentDate.getDate() + 1);
currentDateif (isBusinessDay(currentDate)) {
--;
remainingDays
}
}
return currentDate;
}
// Example
const startDate = new Date('2024-12-24');
console.log(addBusinessDays(startDate, 3)); // Skips Christmas and weekend
Advanced Date Manipulations
Calendar Generation
function generateCalendarMonth(year, month) {
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
const calendar = [];
// Add empty days for the start of the month
let week = Array(firstDay.getDay()).fill(null);
// Fill in the days of the month
for (let day = 1; day <= lastDay.getDate(); day++) {
.push(new Date(year, month, day));
week
if (week.length === 7) {
.push(week);
calendar= [];
week
}
}
// Fill in the rest of the last week if needed
if (week.length > 0) {
.push(week.concat(Array(7 - week.length).fill(null)));
calendar
}
return calendar;
}
// Example
const december2024 = generateCalendarMonth(2024, 11);
console.log(december2024); // 2D array representing the calendar
Age Calculation
function calculateAge(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 {
years: age,
months: monthDiff < 0 ? monthDiff + 12 : monthDiff,
days: today.getDate() - birthDate.getDate()
;
}
}
// Example
const age = calculateAge(new Date('1990-05-15'));
console.log(age); // { years: 34, months: 7, days: 12 }
Recurring Date Patterns
function getNextOccurrence(baseDate, pattern) {
const date = new Date(baseDate);
switch (pattern) {
case 'daily':
.setDate(date.getDate() + 1);
datebreak;
case 'weekly':
.setDate(date.getDate() + 7);
datebreak;
case 'monthly':
.setMonth(date.getMonth() + 1);
datebreak;
case 'yearly':
.setFullYear(date.getFullYear() + 1);
datebreak;
default:
throw new Error('Invalid pattern');
}
return date;
}
function generateRecurringDates(startDate, pattern, count) {
const dates = [new Date(startDate)];
let currentDate = new Date(startDate);
for (let i = 1; i < count; i++) {
= getNextOccurrence(currentDate, pattern);
currentDate .push(new Date(currentDate));
dates
}
return dates;
}
// Example
const recurringDates = generateRecurringDates(
new Date('2024-01-01'),
'monthly',
12
;
)console.log(recurringDates); // Array of dates for each month in 2024
This comprehensive guide covers many common date-related problems you might encounter in JavaScript development. Remember that while these solutions work well for most cases, you might need to adjust them based on your specific requirements, especially when dealing with different time zones or specific business rules.
For production applications, consider using established date manipulation libraries like Moment.js, Day.js, or Luxon, which provide more robust solutions and handle edge cases more reliably. However, understanding these fundamental concepts will help you work with dates more effectively, regardless of whether you’re using vanilla JavaScript or a library.
Remember to always validate your date operations thoroughly, especially when dealing with user input or different time zones. Date manipulation can be tricky, and edge cases are common, so comprehensive testing is essential.