97 lines
2.8 KiB
TypeScript
97 lines
2.8 KiB
TypeScript
/**
|
|
* Formats current date to match SQL datetime format
|
|
* Note: Adds 4 hours to match server timezone (EST)
|
|
* Returns format: YYYY-MM-DD HH:MM:SS
|
|
*/
|
|
export function getSQLFormattedDate(): string {
|
|
const date = new Date();
|
|
date.setHours(date.getHours() + 4);
|
|
|
|
const year = date.getFullYear();
|
|
const month = `${date.getMonth() + 1}`.padStart(2, "0");
|
|
const day = `${date.getDate()}`.padStart(2, "0");
|
|
const hours = `${date.getHours()}`.padStart(2, "0");
|
|
const minutes = `${date.getMinutes()}`.padStart(2, "0");
|
|
const seconds = `${date.getSeconds()}`.padStart(2, "0");
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
}
|
|
|
|
export interface FormatRelativeTimeOptions {
|
|
/**
|
|
* Style of formatting:
|
|
* - "short": "5m ago", "2h ago", "3d ago"
|
|
* - "long": "5 minutes ago", "2 hours ago", "3 days ago"
|
|
*/
|
|
style?: "short" | "long";
|
|
/**
|
|
* Include seconds in the output (only for style="long")
|
|
*/
|
|
includeSeconds?: boolean;
|
|
/**
|
|
* For dates older than this many days, return a formatted date instead
|
|
* If undefined, always returns relative time
|
|
*/
|
|
maxDays?: number;
|
|
/**
|
|
* Locale options for fallback date formatting when maxDays is exceeded
|
|
*/
|
|
dateFormatOptions?: Intl.DateTimeFormatOptions;
|
|
}
|
|
|
|
/**
|
|
* Formats a date as relative time (e.g., "5 minutes ago", "2h ago")
|
|
* @param date - Date to format (can be Date object or ISO string)
|
|
* @param options - Formatting options
|
|
* @returns Formatted relative time string
|
|
*/
|
|
export function formatRelativeTime(
|
|
date: Date | string,
|
|
options: FormatRelativeTimeOptions = {}
|
|
): string {
|
|
const {
|
|
style = "short",
|
|
includeSeconds = false,
|
|
maxDays,
|
|
dateFormatOptions
|
|
} = options;
|
|
|
|
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
const now = new Date();
|
|
const diffMs = now.getTime() - dateObj.getTime();
|
|
const diffSec = Math.floor(diffMs / 1000);
|
|
const diffMin = Math.floor(diffSec / 60);
|
|
const diffHour = Math.floor(diffMin / 60);
|
|
const diffDay = Math.floor(diffHour / 24);
|
|
|
|
// If maxDays is specified and exceeded, return formatted date
|
|
if (maxDays !== undefined && diffDay >= maxDays) {
|
|
return dateObj.toLocaleDateString(
|
|
"en-US",
|
|
dateFormatOptions || { month: "short", day: "numeric" }
|
|
);
|
|
}
|
|
|
|
if (style === "short") {
|
|
if (diffMin < 60) {
|
|
return `${diffMin}m ago`;
|
|
} else if (diffHour < 24) {
|
|
return `${diffHour}h ago`;
|
|
} else {
|
|
return `${diffDay}d ago`;
|
|
}
|
|
} else {
|
|
// style === "long"
|
|
if (includeSeconds && diffSec < 60) {
|
|
return `${diffSec} second${diffSec === 1 ? "" : "s"} ago`;
|
|
}
|
|
if (diffMin < 60) {
|
|
return `${diffMin} minute${diffMin === 1 ? "" : "s"} ago`;
|
|
}
|
|
if (diffHour < 24) {
|
|
return `${diffHour} hour${diffHour === 1 ? "" : "s"} ago`;
|
|
}
|
|
return `${diffDay} day${diffDay === 1 ? "" : "s"} ago`;
|
|
}
|
|
}
|