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
JavaScript
/**
* 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;
}