Module 10: Dates and Time
Working with dates and time is a common requirement in web applications. JavaScript provides the Date object for handling date and time operations, though modern alternatives like Temporal API are emerging.
1. Creating Date Objects
1.1 Current Date and Time
const now = new Date();
console.log(now); // Current date and time
1.2 Specific Date and Time
// Date string
const date1 = new Date('2024-03-15');
const date2 = new Date('March 15, 2024');
const date3 = new Date('2024-03-15T10:30:00');
// Year, month (0-11), day, hour, minute, second, millisecond
const date4 = new Date(2024, 2, 15); // March 15, 2024
const date5 = new Date(2024, 2, 15, 10, 30, 0); // With time
// Timestamp (milliseconds since Jan 1, 1970)
const date6 = new Date(1710504600000);
In the Date constructor, months are 0-indexed: January = 0, December = 11.
2. Getting Date Components
2.1 Get Methods
const date = new Date('2024-03-15T10:30:45');
// Date components
date.getFullYear(); // 2024
date.getMonth(); // 2 (March, 0-indexed)
date.getDate(); // 15 (day of month)
date.getDay(); // 5 (Friday, 0=Sunday)
// Time components
date.getHours(); // 10
date.getMinutes(); // 30
date.getSeconds(); // 45
date.getMilliseconds(); // 0
// Timestamp
date.getTime(); // Milliseconds since Unix epoch
date.valueOf(); // Same as getTime()
2.2 UTC Methods
const date = new Date('2024-03-15T10:30:00Z');
date.getUTCFullYear(); // 2024
date.getUTCMonth(); // 2
date.getUTCDate(); // 15
date.getUTCHours(); // 10
date.getUTCMinutes(); // 30
2.3 Timezone Offset
const date = new Date();
const offsetMinutes = date.getTimezoneOffset();
console.log(`UTC offset: ${offsetMinutes / 60} hours`);
3. Setting Date Components
3.1 Set Methods
const date = new Date('2024-03-15T10:30:00');
// Modify date components
date.setFullYear(2025);
date.setMonth(11); // December
date.setDate(25); // Christmas
// Modify time components
date.setHours(23);
date.setMinutes(59);
date.setSeconds(59);
date.setMilliseconds(999);
// Set from timestamp
date.setTime(1710504600000);
console.log(date); // Modified date
3.2 UTC Set Methods
const date = new Date();
date.setUTCFullYear(2024);
date.setUTCMonth(2);
date.setUTCDate(15);
Set methods return the timestamp, not the date object, so chaining isn't natural. Modify in sequence.
4. Formatting Dates
4.1 Built-in Methods
const date = new Date('2024-03-15T10:30:00');
// String representations
date.toString(); // "Fri Mar 15 2024 10:30:00 GMT+0000"
date.toDateString(); // "Fri Mar 15 2024"
date.toTimeString(); // "10:30:00 GMT+0000"
date.toISOString(); // "2024-03-15T10:30:00.000Z"
date.toUTCString(); // "Fri, 15 Mar 2024 10:30:00 GMT"
date.toJSON(); // "2024-03-15T10:30:00.000Z"
// Localized formatting
date.toLocaleDateString(); // "3/15/2024" (US)
date.toLocaleTimeString(); // "10:30:00 AM"
date.toLocaleString(); // "3/15/2024, 10:30:00 AM"
4.2 Intl.DateTimeFormat API
const date = new Date('2024-03-15T10:30:00');
// Basic formatting
const formatter1 = new Intl.DateTimeFormat('en-US');
console.log(formatter1.format(date)); // "3/15/2024"
// With options
const formatter2 = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
});
console.log(formatter2.format(date)); // "Friday, March 15, 2024"
// Time formatting
const formatter3 = new Intl.DateTimeFormat('en-US', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: true
});
console.log(formatter3.format(date)); // "10:30:00 AM"
// Full date and time
const formatter4 = new Intl.DateTimeFormat('en-US', {
dateStyle: 'full',
timeStyle: 'long'
});
console.log(formatter4.format(date));
// "Friday, March 15, 2024 at 10:30:00 AM UTC"
4.3 Different Locales
const date = new Date('2024-03-15');
console.log(date.toLocaleDateString('en-US')); // "3/15/2024"
console.log(date.toLocaleDateString('en-GB')); // "15/03/2024"
console.log(date.toLocaleDateString('de-DE')); // "15.3.2024"
console.log(date.toLocaleDateString('ja-JP')); // "2024/3/15"
console.log(date.toLocaleDateString('ar-EG')); // "١٥/٣/٢٠٢٤"
4.4 Custom Formatting
function formatDate(date, format = 'YYYY-MM-DD') {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
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 format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', day)
.replace('HH', hours)
.replace('mm', minutes)
.replace('ss', seconds);
}
const date = new Date('2024-03-15T10:30:45');
console.log(formatDate(date, 'YYYY-MM-DD')); // "2024-03-15"
console.log(formatDate(date, 'DD/MM/YYYY')); // "15/03/2024"
console.log(formatDate(date, 'YYYY-MM-DD HH:mm:ss')); // "2024-03-15 10:30:45"
5. Date Arithmetic
5.1 Adding/Subtracting Days
const today = new Date();
// Add 7 days
const nextWeek = new Date(today);
nextWeek.setDate(today.getDate() + 7);
// Subtract 30 days
const lastMonth = new Date(today);
lastMonth.setDate(today.getDate() - 30);
// Add months (handles year overflow)
const nextYear = new Date(today);
nextYear.setMonth(today.getMonth() + 12);
5.2 Date Difference
const date1 = new Date('2024-03-15');
const date2 = new Date('2024-03-20');
// Difference in milliseconds
const diffMs = date2 - date1;
// Convert to days
const diffDays = diffMs / (1000 * 60 * 60 * 24);
console.log(`${diffDays} days`); // 5 days
// Convert to hours
const diffHours = diffMs / (1000 * 60 * 60);
console.log(`${diffHours} hours`); // 120 hours
5.3 Practical Examples
// Days until event
function daysUntil(targetDate) {
const now = new Date();
const target = new Date(targetDate);
const diff = target - now;
return Math.ceil(diff / (1000 * 60 * 60 * 24));
}
console.log(`Days until Christmas: ${daysUntil('2024-12-25')}`);
// Age calculation
function calculateAge(birthDate) {
const today = new Date();
const birth = new Date(birthDate);
let age = today.getFullYear() - birth.getFullYear();
const monthDiff = today.getMonth() - birth.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
age--;
}
return age;
}
console.log(calculateAge('1990-05-15')); // 33 (as of 2024)
// Business days between dates
function businessDaysBetween(startDate, endDate) {
const start = new Date(startDate);
const end = new Date(endDate);
let count = 0;
while (start <= end) {
const dayOfWeek = start.getDay();
if (dayOfWeek !== 0 && dayOfWeek !== 6) { // Not Sunday or Saturday
count++;
}
start.setDate(start.getDate() + 1);
}
return count;
}
console.log(businessDaysBetween('2024-03-01', '2024-03-31'));
6. Comparing Dates
6.1 Comparison Operators
const date1 = new Date('2024-03-15');
const date2 = new Date('2024-03-20');
console.log(date1 < date2); // true
console.log(date1 > date2); // false
console.log(date1 <= date2); // true
console.log(date1 >= date2); // false
// Equality (use getTime() for accurate comparison)
console.log(date1 == date2); // false
console.log(date1 === date2); // false (different objects)
console.log(date1.getTime() === date2.getTime()); // false
6.2 Checking Same Day
function isSameDay(date1, date2) {
return date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate();
}
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
console.log(isSameDay(today, tomorrow)); // false
6.3 Date Range Validation
function isDateInRange(date, startDate, endDate) {
return date >= startDate && date <= endDate;
}
const checkDate = new Date('2024-03-15');
const start = new Date('2024-03-01');
const end = new Date('2024-03-31');
console.log(isDateInRange(checkDate, start, end)); // true
7. Common Date Operations
7.1 Start and End of Day
function startOfDay(date) {
const newDate = new Date(date);
newDate.setHours(0, 0, 0, 0);
return newDate;
}
function endOfDay(date) {
const newDate = new Date(date);
newDate.setHours(23, 59, 59, 999);
return newDate;
}
const today = new Date();
console.log(startOfDay(today)); // Today at 00:00:00
console.log(endOfDay(today)); // Today at 23:59:59
7.2 Start and End of Month
function startOfMonth(date) {
return new Date(date.getFullYear(), date.getMonth(), 1);
}
function endOfMonth(date) {
return new Date(date.getFullYear(), date.getMonth() + 1, 0);
}
const today = new Date();
console.log(startOfMonth(today)); // First day of current month
console.log(endOfMonth(today)); // Last day of current month
7.3 Week Operations
function getWeekNumber(date) {
const firstDayOfYear = new Date(date.getFullYear(), 0, 1);
const pastDaysOfYear = (date - firstDayOfYear) / 86400000;
return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);
}
console.log(getWeekNumber(new Date('2024-03-15'))); // Week number
function getMonday(date) {
const day = date.getDay();
const diff = date.getDate() - day + (day === 0 ? -6 : 1);
return new Date(date.setDate(diff));
}
const today = new Date();
console.log(getMonday(today)); // Monday of current week
8. Timestamps and Unix Time
8.1 Current Timestamp
// Multiple ways to get current timestamp
const timestamp1 = Date.now();
const timestamp2 = new Date().getTime();
const timestamp3 = +new Date();
console.log(timestamp1); // e.g., 1710504600000
8.2 Converting Timestamps
// Timestamp to Date
const timestamp = 1710504600000;
const date = new Date(timestamp);
// Date to Timestamp
const now = new Date();
const nowTimestamp = now.getTime();
// Unix timestamp (seconds)
const unixTimestamp = Math.floor(Date.now() / 1000);
console.log(unixTimestamp); // e.g., 1710504600
8.3 Performance Measurement
// Measure execution time
const start = Date.now();
// Some operation
for (let i = 0; i < 1000000; i++) {
Math.sqrt(i);
}
const end = Date.now();
console.log(`Execution time: ${end - start}ms`);
// Using performance.now() for higher precision
const perfStart = performance.now();
// Some operation
const perfEnd = performance.now();
console.log(`Execution time: ${perfEnd - perfStart}ms`);
9. Date Validation
9.1 Valid Date Check
function isValidDate(dateString) {
const date = new Date(dateString);
return date instanceof Date && !isNaN(date);
}
console.log(isValidDate('2024-03-15')); // true
console.log(isValidDate('invalid')); // false
console.log(isValidDate('2024-13-45')); // false (invalid month/day)
9.2 Leap Year Check
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}
console.log(isLeapYear(2024)); // true
console.log(isLeapYear(2023)); // false
console.log(isLeapYear(2000)); // true
console.log(isLeapYear(1900)); // false
9.3 Date Range Validation
function isDateInPast(date) {
return new Date(date) < new Date();
}
function isDateInFuture(date) {
return new Date(date) > new Date();
}
console.log(isDateInPast('2020-01-01')); // true
console.log(isDateInFuture('2025-12-31')); // true
10. Working with Timezones
10.1 Timezone Formatting
const date = new Date();
// Different timezone displays
const usFormat = date.toLocaleString('en-US', {
timeZone: 'America/New_York',
timeZoneName: 'short'
});
const ukFormat = date.toLocaleString('en-GB', {
timeZone: 'Europe/London',
timeZoneName: 'long'
});
const jpFormat = date.toLocaleString('ja-JP', {
timeZone: 'Asia/Tokyo',
hour12: false
});
console.log('New York:', usFormat);
console.log('London:', ukFormat);
console.log('Tokyo:', jpFormat);
10.2 UTC Conversion
function convertToUTC(date) {
return new Date(date.getTime() + date.getTimezoneOffset() * 60000);
}
function convertFromUTC(date, timezoneOffset) {
return new Date(date.getTime() - timezoneOffset * 60000);
}
11. Common Pitfalls
11.1 Date Mutability
const date1 = new Date('2024-03-15');
const date2 = date1; // Same reference!
date2.setDate(20);
console.log(date1); // Also changed! ❌
// Solution: Create new date
const date3 = new Date(date1);
date3.setDate(25);
console.log(date1); // Unchanged ✅
11.2 Month Zero-Indexing
// Wrong
const march = new Date(2024, 3, 15); // Actually April! ❌
// Correct
const march = new Date(2024, 2, 15); // March ✅
11.3 Date Parsing Inconsistencies
// Can produce different results in different browsers
const date1 = new Date('03/15/2024'); // Risky
const date2 = new Date('2024-03-15'); // Safe (ISO format)
// Always prefer ISO format
const isoDate = new Date('2024-03-15T10:30:00Z'); // ✅
Avoid non-ISO date strings. Use ISO 8601 format (YYYY-MM-DD) for consistency across browsers.
12. Modern Alternatives
12.1 Libraries
Day.js (Lightweight)
import dayjs from 'dayjs';
const date = dayjs('2024-03-15');
console.log(date.format('MMMM DD, YYYY')); // "March 15, 2024"
console.log(date.add(7, 'day').format()); // Add 7 days
date-fns (Functional)
import { format, addDays, differenceInDays } from 'date-fns';
const date = new Date('2024-03-15');
console.log(format(date, 'MMMM dd, yyyy')); // "March 15, 2024"
console.log(addDays(date, 7)); // Add 7 days
Luxon (Immutable)
import { DateTime } from 'luxon';
const dt = DateTime.fromISO('2024-03-15');
console.log(dt.toFormat('MMMM dd, yyyy')); // "March 15, 2024"
console.log(dt.plus({ days: 7 })); // Add 7 days
12.2 Temporal API (Future)
// Upcoming native API (Stage 3 proposal)
const date = Temporal.PlainDate.from('2024-03-15');
const dateTime = Temporal.PlainDateTime.from('2024-03-15T10:30:00');
// Immutable operations
const nextWeek = date.add({ days: 7 });
// Clearer timezone handling
const zonedDateTime = Temporal.ZonedDateTime.from({
year: 2024,
month: 3,
day: 15,
hour: 10,
timeZone: 'America/New_York'
});
The Temporal API will replace the legacy Date object with a modern, immutable, timezone-aware API. It's currently in Stage 3 and not yet in browsers.
Summary
In this module, you learned:
- ✅ Creating and manipulating Date objects
- ✅ Getting and setting date components
- ✅ Formatting dates with built-in methods and Intl API
- ✅ Date arithmetic and calculations
- ✅ Comparing and validating dates
- ✅ Working with timestamps and timezones
- ✅ Common pitfalls and best practices
- ✅ Modern date libraries and upcoming Temporal API
In Module 11, you'll learn about JSON (JavaScript Object Notation) for data serialization and API communication.
Practice Exercises
- Create a function to display current time in multiple timezones
- Build a countdown timer to a specific date
- Calculate the number of days between two dates
- Create a function to format dates in different styles
- Build an age calculator that accounts for leap years
- Implement a date range picker validation
- Create a utility to find the next occurrence of a specific weekday
- Build a function to group dates by week/month/year