learning_ai_clock/web/src/lib/format.ts

74 lines
2.1 KiB
TypeScript

// ── Format Utilities ───────────────────────────────────────────
/**
* Format milliseconds as HH:MM:SS or MM:SS
*/
export function formatDuration(ms: number): string {
if (ms <= 0) return '00:00';
const totalSeconds = Math.floor(ms / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
const pad = (n: number) => n.toString().padStart(2, '0');
if (hours > 0) {
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
}
return `${pad(minutes)}:${pad(seconds)}`;
}
/**
* Format milliseconds as compact string: "2h 15m", "45m", "30s"
*/
export function formatDurationCompact(ms: number): string {
if (ms <= 0) return '0s';
const totalSeconds = Math.floor(ms / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
if (hours > 0 && minutes > 0) return `${hours}h ${minutes}m`;
if (hours > 0) return `${hours}h`;
if (minutes > 0 && seconds > 0 && minutes < 5) return `${minutes}m ${seconds}s`;
if (minutes > 0) return `${minutes}m`;
return `${seconds}s`;
}
/**
* Format a timestamp as relative time: "in 5m", "2h ago", "now"
*/
export function formatRelativeTime(targetTime: number, now: number = Date.now()): string {
const diff = targetTime - now;
const absDiff = Math.abs(diff);
if (absDiff < 30_000) return 'now';
const compact = formatDurationCompact(absDiff);
return diff > 0 ? `in ${compact}` : `${compact} ago`;
}
/**
* Format time as HH:MM AM/PM
*/
export function formatTime(timestamp: number): string {
const date = new Date(timestamp);
return date.toLocaleTimeString('en-US', {
hour: 'numeric',
minute: '2-digit',
hour12: true,
});
}
/**
* Format date as "Mon, Feb 27"
*/
export function formatDate(timestamp: number): string {
const date = new Date(timestamp);
return date.toLocaleDateString('en-US', {
weekday: 'short',
month: 'short',
day: 'numeric',
});
}