import { formatDistanceToNow } from 'date-fns'; /** * Parse and optionally convert a date string to a Date object with timezone handling * @param dateString - The date string to parse * @param isUTC - Whether to convert from UTC to local timezone (default: true) * @returns Processed Date object or null if invalid */ function parseAndConvertDate(dateString: string, isUTC: boolean = true): Date | null { try { // If isUTC is true and the date string doesn't have timezone info, treat it as UTC let dateToProcess = dateString; if (isUTC && !dateString.endsWith('Z') && !dateString.includes('+') && !dateString.includes('-', 10)) { dateToProcess = `${dateString}Z`; } const date = new Date(dateToProcess); if (isNaN(date.getTime())) { return null; } if (!isUTC) { return date; } // Get timezone from localStorage, default to Europe/Paris const timezone = localStorage.getItem('timezone') || 'Europe/Paris'; // Format the date in the target timezone const formatter = new Intl.DateTimeFormat('fr-FR', { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }); const parts = formatter.formatToParts(date); const partsObj = parts.reduce((acc, part) => { acc[part.type] = part.value; return acc; }, {} as Record); // Create new date object in the target timezone return new Date( parseInt(partsObj.year), parseInt(partsObj.month) - 1, // Month is 0-indexed parseInt(partsObj.day), parseInt(partsObj.hour), parseInt(partsObj.minute), parseInt(partsObj.second) ); } catch (error) { console.error('Error parsing date:', error); return null; } } /** * Format a date string to DD/MM/YYYY HH:MM:SS or DD/MM/YYYY * @param dateString - The date string to format * @param withTime - Whether to include time in the output (default: true) * @param isUTC - Whether to convert from UTC to local timezone (default: true) * @returns Formatted date string */ export function formatDate( dateString: string, withTime: boolean = true, isUTC: boolean = true ): string { const date = parseAndConvertDate(dateString, isUTC); if (!date) { return 'Invalid Date'; } const day = date.getDate().toString().padStart(2, '0'); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const year = date.getFullYear().toString(); const dateFormatted = `${day}/${month}/${year}`; if (!withTime) { return dateFormatted; } const hours = date.getHours().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0'); const seconds = date.getSeconds().toString().padStart(2, '0'); return `${dateFormatted} ${hours}:${minutes}:${seconds}`; } /** * Format a date string to show distance to now (e.g., "2 hours ago", "3 days ago") * @param dateString - The date string to format * @param isUTC - Whether to convert from UTC to local timezone (default: true) * @returns Formatted distance string (e.g., "2 hours ago") */ export function formatDateDistanceToNow( dateString: string, isUTC: boolean = true ): string { const date = parseAndConvertDate(dateString, isUTC); if (!date) { return 'Invalid Date'; } return formatDistanceToNow(date, { addSuffix: true }); } /** * Format a date string with timezone consideration * @param dateString - The date string to format * @param timezone - The target timezone (default: 'UTC') * @returns Formatted date string with timezone */ export function formatDateTime(dateString: string, timezone: string = 'UTC'): string { try { const date = new Date(dateString) if (isNaN(date.getTime())) { return 'Invalid Date' } const formatter = new Intl.DateTimeFormat('fr-FR', { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false, }) return formatter.format(date) } catch { return 'Invalid Date' } }