UNPKG

claritykit-svelte

Version:

A comprehensive Svelte component library focused on accessibility, ADHD-optimized design, developer experience, and full SSR compatibility

300 lines (299 loc) 8.84 kB
/** * Date utility functions for ClarityKit * Provides common date formatting, parsing, and calculation functions */ /** * Format a date using various format options * @param date - Date to format * @param format - Format string or preset format * @param locale - Optional locale for formatting */ export function formatDate(date, format = 'short', locale = 'en-US') { const dateObj = new Date(date); if (isNaN(dateObj.getTime())) { return 'Invalid Date'; } // Preset formats const presets = { short: { month: 'short', day: 'numeric', year: 'numeric' }, long: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }, numeric: { month: '2-digit', day: '2-digit', year: 'numeric' }, time: { hour: '2-digit', minute: '2-digit' }, datetime: { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit' }, iso: undefined, // Special case for ISO string relative: undefined // Special case for relative time }; if (format === 'iso') { return dateObj.toISOString().split('T')[0]; } if (format === 'relative') { return formatRelativeDate(dateObj); } if (presets[format]) { return dateObj.toLocaleDateString(locale, presets[format]); } // Custom format string handling (simplified) let result = format; const year = dateObj.getFullYear(); const month = dateObj.getMonth() + 1; const day = dateObj.getDate(); const hours = dateObj.getHours(); const minutes = dateObj.getMinutes(); result = result.replace(/YYYY/g, year.toString()); result = result.replace(/MM/g, month.toString().padStart(2, '0')); result = result.replace(/DD/g, day.toString().padStart(2, '0')); result = result.replace(/HH/g, hours.toString().padStart(2, '0')); result = result.replace(/mm/g, minutes.toString().padStart(2, '0')); return result; } /** * Format a date relative to now (e.g., "2 days ago", "in 3 hours") */ export function formatRelativeDate(date) { const dateObj = new Date(date); const now = new Date(); const diffMs = now.getTime() - dateObj.getTime(); const diffSeconds = Math.floor(diffMs / 1000); const diffMinutes = Math.floor(diffSeconds / 60); const diffHours = Math.floor(diffMinutes / 60); const diffDays = Math.floor(diffHours / 24); if (Math.abs(diffSeconds) < 60) { return 'just now'; } else if (Math.abs(diffMinutes) < 60) { const unit = Math.abs(diffMinutes) === 1 ? 'minute' : 'minutes'; return diffMinutes > 0 ? `${Math.abs(diffMinutes)} ${unit} ago` : `in ${Math.abs(diffMinutes)} ${unit}`; } else if (Math.abs(diffHours) < 24) { const unit = Math.abs(diffHours) === 1 ? 'hour' : 'hours'; return diffHours > 0 ? `${Math.abs(diffHours)} ${unit} ago` : `in ${Math.abs(diffHours)} ${unit}`; } else if (Math.abs(diffDays) < 30) { const unit = Math.abs(diffDays) === 1 ? 'day' : 'days'; return diffDays > 0 ? `${Math.abs(diffDays)} ${unit} ago` : `in ${Math.abs(diffDays)} ${unit}`; } else { return formatDate(dateObj, 'short'); } } /** * Parse a date string or number into a Date object */ export function parseDate(date) { try { const parsed = new Date(date); return isNaN(parsed.getTime()) ? null : parsed; } catch { return null; } } /** * Convert a date to ISO date string (YYYY-MM-DD) */ export function toISODateString(date) { const dateObj = new Date(date); if (isNaN(dateObj.getTime())) { throw new Error('Invalid date'); } return dateObj.toISOString().split('T')[0]; } /** * Calculate the number of days between two dates */ export function daysBetween(date1, date2) { const d1 = new Date(date1); const d2 = new Date(date2); if (isNaN(d1.getTime()) || isNaN(d2.getTime())) { throw new Error('Invalid date provided'); } const diffTime = Math.abs(d2.getTime() - d1.getTime()); return Math.ceil(diffTime / (1000 * 60 * 60 * 24)); } /** * Check if a year is a leap year */ export function isLeapYear(year) { return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0); } /** * Get the number of days in a specific month */ export function getDaysInMonth(year, month) { return new Date(year, month, 0).getDate(); } /** * Check if two dates are on the same day */ export function isSameDay(date1, date2) { const d1 = new Date(date1); const d2 = new Date(date2); return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate(); } /** * Add days to a date */ export function addDays(date, days) { const result = new Date(date); result.setDate(result.getDate() + days); return result; } /** * Add months to a date */ export function addMonths(date, months) { const result = new Date(date); result.setMonth(result.getMonth() + months); return result; } /** * Get the start of day for a date (00:00:00) */ export function startOfDay(date) { const result = new Date(date); result.setHours(0, 0, 0, 0); return result; } /** * Get the end of day for a date (23:59:59.999) */ export function endOfDay(date) { const result = new Date(date); result.setHours(23, 59, 59, 999); return result; } /** * Check if a date is today */ export function isToday(date) { return isSameDay(date, new Date()); } /** * Check if a date is in the past */ export function isPast(date) { return new Date(date) < new Date(); } /** * Check if a date is in the future */ export function isFuture(date) { return new Date(date) > new Date(); } /** * Format duration in milliseconds to human-readable string */ export function formatDuration(ms) { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) { const remainingHours = hours % 24; return remainingHours > 0 ? `${days}d ${remainingHours}h` : `${days}d`; } else if (hours > 0) { const remainingMinutes = minutes % 60; return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`; } else if (minutes > 0) { const remainingSeconds = seconds % 60; return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`; } else { return `${seconds}s`; } } /** * Get the age in years from a birth date */ export function getAge(birthDate) { const birth = new Date(birthDate); const today = new Date(); let age = today.getFullYear() - birth.getFullYear(); const monthDiff = today.getMonth() - birth.getMonth(); if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) { age--; } return age; } /** * Format date and time together */ export function formatDateTime(date, locale = 'en-US') { return formatDate(date, 'datetime', locale); } /** * Format relative time (alias for formatRelativeDate) */ export function formatRelativeTime(date) { return formatRelativeDate(date); } /** * Check if a date is yesterday */ export function isYesterday(date) { const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); return isSameDay(date, yesterday); } /** * Check if a date is tomorrow */ export function isTomorrow(date) { const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); return isSameDay(date, tomorrow); } /** * Subtract days from a date */ export function subDays(date, days) { return addDays(date, -days); } /** * Get the start of the month for a date */ export function startOfMonth(date) { const result = new Date(date); result.setDate(1); result.setHours(0, 0, 0, 0); return result; } /** * Get the end of the month for a date */ export function endOfMonth(date) { const result = new Date(date); result.setMonth(result.getMonth() + 1, 0); result.setHours(23, 59, 59, 999); return result; } /** * Get the start of the week for a date (Sunday by default) */ export function startOfWeek(date, weekStartsOn = 0) { const result = new Date(date); const day = result.getDay(); const diff = (day + 7 - weekStartsOn) % 7; result.setDate(result.getDate() - diff); result.setHours(0, 0, 0, 0); return result; } /** * Get the end of the week for a date (Saturday by default) */ export function endOfWeek(date, weekStartsOn = 0) { const result = startOfWeek(date, weekStartsOn); result.setDate(result.getDate() + 6); result.setHours(23, 59, 59, 999); return result; }