Skip to main content

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);
Month is Zero-Based

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);
Method Chaining

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'); // ✅
Date Parsing

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'
});
Temporal API

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
Next Steps

In Module 11, you'll learn about JSON (JavaScript Object Notation) for data serialization and API communication.


Practice Exercises​

  1. Create a function to display current time in multiple timezones
  2. Build a countdown timer to a specific date
  3. Calculate the number of days between two dates
  4. Create a function to format dates in different styles
  5. Build an age calculator that accounts for leap years
  6. Implement a date range picker validation
  7. Create a utility to find the next occurrence of a specific weekday
  8. Build a function to group dates by week/month/year

Additional Resources​