/**
* Format a date string (YYYY-MM-DD HH:MM:SS) to a relative time string.
* Examples: "just now", "5 min ago", "1 hour ago", "2 days ago", "1 week ago", "1 month ago"
* @param {string|null} dateString - Date string in format "YYYY-MM-DD HH:MM:SS" or ISO
* @returns {string} Relative time string
*/
export function formatRelative(dateString) {
if (!dateString) return "";
const date = parseDate(dateString);
if (!date) return dateString;
const now = new Date();
const diffMs = now - date;
const diffSecs = Math.floor(diffMs / 1000);
const diffMins = Math.floor(diffSecs / 60);
const diffHours = Math.floor(diffMins / 60);
const diffDays = Math.floor(diffHours / 24);
const diffWeeks = Math.floor(diffDays / 7);
const diffMonths = Math.floor(diffDays / 30);
if (diffSecs < 10) return "just now";
if (diffSecs < 60) return `${diffSecs} sec ago`;
if (diffMins < 60) return `${diffMins} min ago`;
if (diffHours < 24) {
const remainderMins = diffMins % 60;
if (remainderMins > 0) {
return `${diffHours} hour${diffHours > 1 ? "s" : ""} ${remainderMins} min ago`;
}
return `${diffHours} hour${diffHours > 1 ? "s" : ""} ago`;
}
if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? "s" : ""} ago`;
if (diffWeeks < 4) return `${diffWeeks} week${diffWeeks > 1 ? "s" : ""} ago`;
if (diffMonths < 12) return `${diffMonths} month${diffMonths > 1 ? "s" : ""} ago`;
const diffYears = Math.floor(diffDays / 365);
return `${diffYears} year${diffYears > 1 ? "s" : ""} ago`;
}
/**
* Format a date string to a readable format for tooltips.
* Returns: "Jun 8, 2026 14:30" or "8 Jun 2026 14:30"
* @param {string|null} dateString - Date string in format "YYYY-MM-DD HH:MM:SS" or ISO
* @returns {string} Formatted date string
*/
export function formatDateTime(dateString) {
if (!dateString) return "";
const date = parseDate(dateString);
if (!date) return dateString;
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const month = months[date.getMonth()];
const day = date.getDate();
const year = date.getFullYear();
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
return `${month} ${day}, ${year} ${hours}:${minutes}`;
}
/**
* Format a date string to a short date format.
* Returns: "Jun 8, 2026"
* @param {string|null} dateString - Date string in format "YYYY-MM-DD HH:MM:SS" or ISO
* @returns {string} Short date string
*/
export function formatDate(dateString) {
if (!dateString) return "";
const date = parseDate(dateString);
if (!date) return dateString;
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const month = months[date.getMonth()];
const day = date.getDate();
const year = date.getFullYear();
return `${month} ${day}, ${year}`;
}
/**
* Parse a date string in various formats to a Date object.
* @param {string} dateString - Date string in format "YYYY-MM-DD HH:MM:SS" or ISO
* @returns {Date|null} Parsed Date object or null if invalid
*/
function parseDate(dateString) {
if (!dateString) return null;
// Handle "YYYY-MM-DD HH:MM:SS" format (MySQL datetime)
const mysqlDateTimeRegex = /^(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})$/;
const match = dateString.match(mysqlDateTimeRegex);
if (match) {
const [, year, month, day, hours, mins, secs] = match;
return new Date(year, parseInt(month) - 1, day, hours, mins, secs);
}
// Try ISO format and other standard formats
const parsed = new Date(dateString);
if (!isNaN(parsed.getTime())) {
return parsed;
}
return null;
}