// Date and time utility functions /** * Date and time utility functions */ export class DateUtils { /** * Get start of week for a given date */ static getWeekStart(date: Date, firstDayOfWeek: number = 1): Date { const d = new Date(date); const day = d.getDay(); const diff = (day - firstDayOfWeek + 7) % 7; d.setDate(d.getDate() - diff); d.setHours(0, 0, 0, 0); return d; } /** * Get end of week for a given date */ static getWeekEnd(date: Date, firstDayOfWeek: number = 1): Date { const start = this.getWeekStart(date, firstDayOfWeek); const end = new Date(start); end.setDate(end.getDate() + 6); end.setHours(23, 59, 59, 999); return end; } /** * Format date to YYYY-MM-DD */ static formatDate(date: Date): string { return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`; } /** * Format time to HH:MM */ static formatTime(date: Date): string { return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`; } /** * Format time to 12-hour format */ static formatTime12(date: Date): string { const hours = date.getHours(); const minutes = date.getMinutes(); const period = hours >= 12 ? 'PM' : 'AM'; const displayHours = hours % 12 || 12; return `${displayHours}:${String(minutes).padStart(2, '0')} ${period}`; } /** * Convert minutes since midnight to time string */ static minutesToTime(minutes: number): string { const hours = Math.floor(minutes / 60); const mins = minutes % 60; const period = hours >= 12 ? 'PM' : 'AM'; const displayHours = hours % 12 || 12; return `${displayHours}:${String(mins).padStart(2, '0')} ${period}`; } /** * Convert time string to minutes since midnight */ static timeToMinutes(timeStr: string): number { const [time] = timeStr.split('T').pop()!.split('.'); const [hours, minutes] = time.split(':').map(Number); return hours * 60 + minutes; } /** * Get minutes since start of day */ static getMinutesSinceMidnight(date: Date | string): number { const d = typeof date === 'string' ? new Date(date) : date; return d.getHours() * 60 + d.getMinutes(); } /** * Calculate duration in minutes between two dates */ static getDurationMinutes(start: Date | string, end: Date | string): number { const startDate = typeof start === 'string' ? new Date(start) : start; const endDate = typeof end === 'string' ? new Date(end) : end; return Math.floor((endDate.getTime() - startDate.getTime()) / 60000); } /** * Check if date is today */ static isToday(date: Date): boolean { const today = new Date(); return date.toDateString() === today.toDateString(); } /** * Check if two dates are on the same day */ static isSameDay(date1: Date, date2: Date): boolean { return date1.toDateString() === date2.toDateString(); } /** * Check if event spans multiple days */ static isMultiDay(start: Date | string, end: Date | string): boolean { const startDate = typeof start === 'string' ? new Date(start) : start; const endDate = typeof end === 'string' ? new Date(end) : end; return !this.isSameDay(startDate, endDate); } /** * Get day name */ static getDayName(date: Date, format: 'short' | 'long' = 'short'): string { const days = { short: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], long: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] }; return days[format][date.getDay()]; } /** * Add days to date */ static addDays(date: Date, days: number): Date { const result = new Date(date); result.setDate(result.getDate() + days); return result; } /** * Add minutes to date */ static addMinutes(date: Date, minutes: number): Date { const result = new Date(date); result.setMinutes(result.getMinutes() + minutes); return result; } /** * Snap time to nearest interval */ static snapToInterval(date: Date, intervalMinutes: number): Date { const minutes = date.getMinutes(); const snappedMinutes = Math.round(minutes / intervalMinutes) * intervalMinutes; const result = new Date(date); result.setMinutes(snappedMinutes); result.setSeconds(0); result.setMilliseconds(0); return result; } /** * Get current time in minutes since day start */ static getCurrentTimeMinutes(dayStartHour: number = 0): number { const now = new Date(); const minutesSinceMidnight = now.getHours() * 60 + now.getMinutes(); return minutesSinceMidnight - (dayStartHour * 60); } /** * Format duration to human readable string */ static formatDuration(minutes: number): string { if (minutes < 60) { return `${minutes} min`; } const hours = Math.floor(minutes / 60); const mins = minutes % 60; if (mins === 0) { return `${hours} hour${hours > 1 ? 's' : ''}`; } return `${hours} hour${hours > 1 ? 's' : ''} ${mins} min`; } /** * Get ISO week number for a given date */ static getWeekNumber(date: Date): number { 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.getTime() - yearStart.getTime()) / 86400000) + 1) / 7); } /** * Get month names array */ static getMonthNames(format: 'short' | 'long' = 'short'): string[] { const months = { short: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], long: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }; return months[format]; } /** * Format date range for display (e.g., "Jan 15 - 21, 2024" or "Jan 15 - Feb 2, 2024") */ static formatDateRange(startDate: Date, endDate: Date): string { const monthNames = this.getMonthNames('short'); const startMonth = monthNames[startDate.getMonth()]; const endMonth = monthNames[endDate.getMonth()]; const startDay = startDate.getDate(); const endDay = endDate.getDate(); const startYear = startDate.getFullYear(); const endYear = endDate.getFullYear(); if (startMonth === endMonth && startYear === endYear) { return `${startMonth} ${startDay} - ${endDay}, ${startYear}`; } else if (startYear !== endYear) { return `${startMonth} ${startDay}, ${startYear} - ${endMonth} ${endDay}, ${endYear}`; } else { return `${startMonth} ${startDay} - ${endMonth} ${endDay}, ${startYear}`; } } }