JavaScript Fundamentals
JavaScript Date and Time: Complete Guide
Master date and time handling in JavaScript. Learn Date objects, formatting, time zones, calculations, and modern date libraries.
By JavaScriptDoc Team•
datetimejavascriptdatetimetimezone
JavaScript Date and Time: Complete Guide
Working with dates and times is a common requirement in JavaScript applications. The Date object provides functionality for handling dates, times, and time zones.
Creating Date Objects
Date Constructors
// Current date and time
const now = new Date();
console.log(now); // Current date and time
// Specific date from string
const date1 = new Date('2024-03-15');
const date2 = new Date('March 15, 2024');
const date3 = new Date('2024-03-15T10:30:00');
// Date from components
const date4 = new Date(2024, 2, 15); // Month is 0-indexed (2 = March)
const date5 = new Date(2024, 2, 15, 10, 30, 0, 0); // With time
// From timestamp (milliseconds since epoch)
const date6 = new Date(1710497400000);
const date7 = new Date(0); // Unix epoch: January 1, 1970
// Invalid dates
const invalid = new Date('invalid');
console.log(invalid); // Invalid Date
console.log(isNaN(invalid)); // true
// Date validation
function isValidDate(date) {
return date instanceof Date && !isNaN(date);
}
Date Parsing
// Date.parse() returns timestamp
const timestamp1 = Date.parse('2024-03-15');
const timestamp2 = Date.parse('March 15, 2024 10:30:00');
// ISO 8601 format (recommended)
const isoDate = new Date('2024-03-15T10:30:00.000Z');
const isoDateLocal = new Date('2024-03-15T10:30:00'); // Local time
// Different formats
const formats = [
'2024-03-15',
'2024/03/15',
'03/15/2024',
'March 15, 2024',
'Mar 15 2024',
'15 Mar 2024',
'2024-03-15 10:30:00',
'2024-03-15T10:30:00.000Z',
];
formats.forEach((format) => {
console.log(`${format}: ${new Date(format)}`);
});
// UTC vs Local time
const utcDate = new Date(Date.UTC(2024, 2, 15, 10, 30));
const localDate = new Date(2024, 2, 15, 10, 30);
console.log('UTC:', utcDate.toISOString());
console.log('Local:', localDate.toString());
Getting Date Components
const date = new Date('2024-03-15T10:30:45.123Z');
// Local time methods
console.log(date.getFullYear()); // 2024
console.log(date.getMonth()); // 2 (0-indexed, March)
console.log(date.getDate()); // 15 (day of month)
console.log(date.getDay()); // 5 (day of week, 0=Sunday)
console.log(date.getHours()); // Local hour
console.log(date.getMinutes()); // 30
console.log(date.getSeconds()); // 45
console.log(date.getMilliseconds()); // 123
console.log(date.getTime()); // Timestamp in milliseconds
// UTC methods
console.log(date.getUTCFullYear()); // 2024
console.log(date.getUTCMonth()); // 2
console.log(date.getUTCDate()); // 15
console.log(date.getUTCHours()); // 10 (UTC hour)
console.log(date.getUTCMinutes()); // 30
// Time zone offset
console.log(date.getTimezoneOffset()); // Minutes from UTC
// Helper functions
function getDateParts(date) {
return {
year: date.getFullYear(),
month: date.getMonth() + 1, // Convert to 1-indexed
day: date.getDate(),
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds(),
dayOfWeek: date.getDay(),
timestamp: date.getTime(),
};
}
// Day names
function getDayName(date) {
const days = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
];
return days[date.getDay()];
}
// Month names
function getMonthName(date) {
const months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
return months[date.getMonth()];
}
Setting Date Components
const date = new Date();
// Set individual components
date.setFullYear(2025);
date.setMonth(11); // December (0-indexed)
date.setDate(25); // Day of month
date.setHours(18);
date.setMinutes(30);
date.setSeconds(0);
date.setMilliseconds(0);
// Set multiple components
date.setHours(20, 0, 0, 0); // hours, minutes, seconds, milliseconds
// UTC setters
date.setUTCFullYear(2025);
date.setUTCMonth(11);
date.setUTCHours(18);
// Set from timestamp
date.setTime(1735156200000);
// Chaining setters
function setDateTime(year, month, day, hours = 0, minutes = 0, seconds = 0) {
return new Date()
.setFullYear(year)
.setMonth(month - 1) // Convert to 0-indexed
.setDate(day)
.setHours(hours, minutes, seconds, 0);
}
// Add/subtract time
function addDays(date, days) {
const result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
function addMonths(date, months) {
const result = new Date(date);
result.setMonth(result.getMonth() + months);
return result;
}
function addHours(date, hours) {
const result = new Date(date);
result.setHours(result.getHours() + hours);
return result;
}
Date Formatting
Built-in Formatting Methods
const date = new Date('2024-03-15T10:30:00');
// String representations
console.log(date.toString());
// Fri Mar 15 2024 10:30:00 GMT-0700 (PDT)
console.log(date.toISOString());
// 2024-03-15T17:30:00.000Z
console.log(date.toUTCString());
// Fri, 15 Mar 2024 17:30:00 GMT
console.log(date.toDateString());
// Fri Mar 15 2024
console.log(date.toTimeString());
// 10:30:00 GMT-0700 (PDT)
console.log(date.toLocaleDateString());
// 3/15/2024
console.log(date.toLocaleTimeString());
// 10:30:00 AM
console.log(date.toLocaleString());
// 3/15/2024, 10:30:00 AM
// JSON representation
console.log(date.toJSON());
// 2024-03-15T17:30:00.000Z
Locale-Specific Formatting
const date = new Date('2024-03-15T10:30:00');
// Different locales
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
// With options
const options = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timeZoneName: 'short',
};
console.log(date.toLocaleString('en-US', options));
// Friday, March 15, 2024 at 10:30:00 AM PDT
// Custom formatting options
const dateOptions = {
dateStyle: 'full', // 'full', 'long', 'medium', 'short'
};
const timeOptions = {
timeStyle: 'medium', // 'full', 'long', 'medium', 'short'
};
// Intl.DateTimeFormat for more control
const formatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false,
});
console.log(formatter.format(date)); // 03/15/2024, 10:30
Custom Formatting Functions
// Format date as YYYY-MM-DD
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}`;
}
// Format time as HH:MM:SS
function formatTime(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 `${hours}:${minutes}:${seconds}`;
}
// Format as ISO string with timezone
function formatISO(date) {
const offset = -date.getTimezoneOffset();
const sign = offset >= 0 ? '+' : '-';
const absOffset = Math.abs(offset);
const hours = Math.floor(absOffset / 60)
.toString()
.padStart(2, '0');
const minutes = (absOffset % 60).toString().padStart(2, '0');
return date.toISOString().slice(0, -1) + sign + hours + ':' + minutes;
}
// Relative time formatting
function formatRelativeTime(date) {
const now = new Date();
const diff = now - date;
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) return `${days} day${days > 1 ? 's' : ''} ago`;
if (hours > 0) return `${hours} hour${hours > 1 ? 's' : ''} ago`;
if (minutes > 0) return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
return `${seconds} second${seconds !== 1 ? 's' : ''} ago`;
}
// Custom format string
function customFormat(date, format) {
const map = {
YYYY: date.getFullYear(),
YY: date.getFullYear().toString().slice(-2),
MM: String(date.getMonth() + 1).padStart(2, '0'),
M: date.getMonth() + 1,
DD: String(date.getDate()).padStart(2, '0'),
D: date.getDate(),
HH: String(date.getHours()).padStart(2, '0'),
H: date.getHours(),
mm: String(date.getMinutes()).padStart(2, '0'),
m: date.getMinutes(),
ss: String(date.getSeconds()).padStart(2, '0'),
s: date.getSeconds(),
};
return format.replace(
/YYYY|YY|MM|M|DD|D|HH|H|mm|m|ss|s/g,
(match) => map[match]
);
}
// Usage
const date = new Date();
console.log(customFormat(date, 'YYYY-MM-DD HH:mm:ss'));
console.log(customFormat(date, 'DD/MM/YY'));
Date Calculations
Date Arithmetic
// Add/subtract days
function addDays(date, days) {
const result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
// Add/subtract with overflow handling
function addMonths(date, months) {
const result = new Date(date);
const originalDay = result.getDate();
result.setMonth(result.getMonth() + months);
// Handle month overflow (e.g., Jan 31 + 1 month)
if (result.getDate() !== originalDay) {
result.setDate(0); // Last day of previous month
}
return result;
}
// Complex date arithmetic
class DateCalculator {
static add(
date,
{ years = 0, months = 0, days = 0, hours = 0, minutes = 0, seconds = 0 }
) {
const result = new Date(date);
if (years) result.setFullYear(result.getFullYear() + years);
if (months) result.setMonth(result.getMonth() + months);
if (days) result.setDate(result.getDate() + days);
if (hours) result.setHours(result.getHours() + hours);
if (minutes) result.setMinutes(result.getMinutes() + minutes);
if (seconds) result.setSeconds(result.getSeconds() + seconds);
return result;
}
static subtract(date, duration) {
return this.add(date, {
years: -(duration.years || 0),
months: -(duration.months || 0),
days: -(duration.days || 0),
hours: -(duration.hours || 0),
minutes: -(duration.minutes || 0),
seconds: -(duration.seconds || 0),
});
}
}
// Date difference
function dateDiff(date1, date2) {
const diff = Math.abs(date2 - date1);
return {
milliseconds: diff,
seconds: Math.floor(diff / 1000),
minutes: Math.floor(diff / (1000 * 60)),
hours: Math.floor(diff / (1000 * 60 * 60)),
days: Math.floor(diff / (1000 * 60 * 60 * 24)),
weeks: Math.floor(diff / (1000 * 60 * 60 * 24 * 7)),
};
}
// 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 age;
}
Date Comparisons
// Basic comparison
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.getTime() === date2.getTime()); // false
// Comparison functions
function isSameDay(date1, date2) {
return (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
}
function isBefore(date1, date2) {
return date1.getTime() < date2.getTime();
}
function isAfter(date1, date2) {
return date1.getTime() > date2.getTime();
}
function isBetween(date, start, end) {
return date >= start && date <= end;
}
// Date range validation
function isDateInRange(date, startDate, endDate) {
return date >= startDate && date <= endDate;
}
// Business days calculation
function addBusinessDays(date, days) {
const result = new Date(date);
let count = 0;
while (count < days) {
result.setDate(result.getDate() + 1);
const dayOfWeek = result.getDay();
// Skip weekends (0 = Sunday, 6 = Saturday)
if (dayOfWeek !== 0 && dayOfWeek !== 6) {
count++;
}
}
return result;
}
function getBusinessDaysBetween(startDate, endDate) {
let count = 0;
const current = new Date(startDate);
while (current <= endDate) {
const dayOfWeek = current.getDay();
if (dayOfWeek !== 0 && dayOfWeek !== 6) {
count++;
}
current.setDate(current.getDate() + 1);
}
return count;
}
Time Zones
// Getting timezone information
const date = new Date();
console.log(date.getTimezoneOffset()); // Minutes from UTC
// Convert to different timezone
function convertToTimezone(date, timeZone) {
return new Date(date.toLocaleString('en-US', { timeZone }));
}
// Get time in specific timezone
function getTimeInTimezone(timeZone) {
return new Date().toLocaleString('en-US', {
timeZone,
dateStyle: 'short',
timeStyle: 'medium',
});
}
// Common timezones
const timezones = [
'UTC',
'America/New_York',
'America/Chicago',
'America/Denver',
'America/Los_Angeles',
'Europe/London',
'Europe/Paris',
'Asia/Tokyo',
'Australia/Sydney',
];
timezones.forEach((tz) => {
console.log(`${tz}: ${getTimeInTimezone(tz)}`);
});
// Timezone-aware date formatting
class TimezoneDate {
constructor(date, timezone) {
this.date = date;
this.timezone = timezone;
}
format(options = {}) {
return this.date.toLocaleString('en-US', {
...options,
timeZone: this.timezone,
});
}
getComponents() {
const formatted = this.format({
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
});
const [date, time] = formatted.split(', ');
const [month, day, year] = date.split('/');
const [hour, minute, second] = time.split(':');
return {
year: parseInt(year),
month: parseInt(month),
day: parseInt(day),
hour: parseInt(hour),
minute: parseInt(minute),
second: parseInt(second),
};
}
}
Working with Timestamps
// Current timestamp
const now = Date.now();
const timestamp = new Date().getTime();
const valueOf = new Date().valueOf();
console.log(now === timestamp); // true (approximately)
// Performance timing
function measureTime(fn) {
const start = performance.now();
const result = fn();
const end = performance.now();
return {
result,
time: end - start,
};
}
// Unix timestamp conversion
function toUnixTimestamp(date) {
return Math.floor(date.getTime() / 1000);
}
function fromUnixTimestamp(timestamp) {
return new Date(timestamp * 1000);
}
// High-resolution timestamps
function getHighResTimestamp() {
return performance.now() + performance.timeOrigin;
}
// Timestamp utilities
class TimestampUtils {
static toSeconds(timestamp) {
return Math.floor(timestamp / 1000);
}
static toMinutes(timestamp) {
return Math.floor(timestamp / (1000 * 60));
}
static toHours(timestamp) {
return Math.floor(timestamp / (1000 * 60 * 60));
}
static toDays(timestamp) {
return Math.floor(timestamp / (1000 * 60 * 60 * 24));
}
static format(timestamp) {
const date = new Date(timestamp);
return date.toISOString();
}
}
Practical Examples
Calendar Component
class Calendar {
constructor(year, month) {
this.year = year;
this.month = month;
}
getDaysInMonth() {
return new Date(this.year, this.month + 1, 0).getDate();
}
getFirstDayOfWeek() {
return new Date(this.year, this.month, 1).getDay();
}
generateCalendar() {
const daysInMonth = this.getDaysInMonth();
const firstDay = this.getFirstDayOfWeek();
const calendar = [];
let week = new Array(firstDay).fill(null);
for (let day = 1; day <= daysInMonth; day++) {
week.push(day);
if (week.length === 7) {
calendar.push(week);
week = [];
}
}
if (week.length > 0) {
while (week.length < 7) {
week.push(null);
}
calendar.push(week);
}
return calendar;
}
getMonthName() {
const months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
return months[this.month];
}
render() {
const calendar = this.generateCalendar();
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
console.log(`${this.getMonthName()} ${this.year}`);
console.log(days.join(' '));
calendar.forEach((week) => {
const weekStr = week
.map((day) => (day ? String(day).padStart(3) : ' '))
.join(' ');
console.log(weekStr);
});
}
}
Countdown Timer
class CountdownTimer {
constructor(targetDate, onUpdate, onComplete) {
this.targetDate = new Date(targetDate);
this.onUpdate = onUpdate;
this.onComplete = onComplete;
this.intervalId = null;
}
start() {
this.update();
this.intervalId = setInterval(() => this.update(), 1000);
}
stop() {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
}
update() {
const now = new Date();
const diff = this.targetDate - now;
if (diff <= 0) {
this.stop();
if (this.onComplete) this.onComplete();
return;
}
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
if (this.onUpdate) {
this.onUpdate({ days, hours, minutes, seconds });
}
}
getRemainingTime() {
const now = new Date();
const diff = this.targetDate - now;
if (diff <= 0) return null;
return {
total: diff,
days: Math.floor(diff / (1000 * 60 * 60 * 24)),
hours: Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
minutes: Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)),
seconds: Math.floor((diff % (1000 * 60)) / 1000),
};
}
}
// Usage
const timer = new CountdownTimer(
'2024-12-31T23:59:59',
(time) => {
console.log(
`${time.days}d ${time.hours}h ${time.minutes}m ${time.seconds}s`
);
},
() => {
console.log('Countdown complete!');
}
);
Date Validator
class DateValidator {
static isValidDate(dateString) {
const date = new Date(dateString);
return date instanceof Date && !isNaN(date);
}
static isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
static isWeekend(date) {
const day = date.getDay();
return day === 0 || day === 6;
}
static isBusinessDay(date) {
return !this.isWeekend(date);
}
static isFutureDate(date) {
return date > new Date();
}
static isPastDate(date) {
return date < new Date();
}
static isToday(date) {
const today = new Date();
return (
date.getFullYear() === today.getFullYear() &&
date.getMonth() === today.getMonth() &&
date.getDate() === today.getDate()
);
}
static validateDateRange(startDate, endDate) {
if (!this.isValidDate(startDate) || !this.isValidDate(endDate)) {
return { valid: false, error: 'Invalid date format' };
}
const start = new Date(startDate);
const end = new Date(endDate);
if (start > end) {
return { valid: false, error: 'Start date must be before end date' };
}
return { valid: true };
}
}
Best Practices
-
Always validate dates
function parseDate(dateString) { const date = new Date(dateString); if (isNaN(date)) { throw new Error('Invalid date'); } return date; }
-
Use ISO format for consistency
// Good: ISO format const date = new Date('2024-03-15T10:30:00Z'); // Avoid: Ambiguous formats const ambiguous = new Date('03/15/2024');
-
Be careful with time zones
// Always specify timezone when important const utcDate = new Date(Date.UTC(2024, 2, 15, 10, 30)); const localDate = new Date(2024, 2, 15, 10, 30);
-
Use libraries for complex operations
// Consider using date-fns, moment.js, or dayjs // for complex date manipulations
Conclusion
JavaScript's Date object provides comprehensive date and time functionality:
- Creating dates from various formats
- Getting and setting date components
- Formatting for display
- Calculations and comparisons
- Time zone handling
- Practical patterns for real-world use
Key takeaways:
- Always validate date inputs
- Be aware of time zone differences
- Use ISO format for consistency
- Consider third-party libraries for complex operations
- Test edge cases like leap years and DST
- Remember months are 0-indexed
Master date and time handling to build robust applications with temporal logic!