fabro/apps/arc-web/app/lib/time.ts
Bryan Helmkamp 2b802835db Extract shared relativeTime helper from timeAgo and timeUntil
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-06 13:42:49 -05:00

67 lines
2.1 KiB
TypeScript

function relativeTime(seconds: number, past: boolean): string {
if (seconds < 60) return past ? "just now" : "in <1m";
const minutes = Math.floor(seconds / 60);
if (minutes < 60) return past ? `${minutes}m ago` : `in ${minutes}m`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return past ? `${hours}h ago` : `in ${hours}h`;
const days = Math.floor(hours / 24);
return past ? `${days}d ago` : `in ${days}d`;
}
/**
* Format an ISO 8601 timestamp as a relative past time string (e.g. "2h ago", "3d ago").
*/
export function timeAgo(iso: string): string {
return relativeTime(Math.floor((Date.now() - new Date(iso).getTime()) / 1000), true);
}
/**
* Format an ISO 8601 timestamp as a relative future time string (e.g. "in 2h", "in 3d").
*/
export function timeUntil(iso: string): string {
return relativeTime(Math.floor((new Date(iso).getTime() - Date.now()) / 1000), false);
}
/**
* Return a human-readable date label for grouping (e.g. "Today", "Yesterday", "Previous 7 days").
*/
function dateLabel(iso: string): string {
const now = new Date();
const date = new Date(iso);
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const startOfYesterday = new Date(startOfToday.getTime() - 86_400_000);
const startOf7DaysAgo = new Date(startOfToday.getTime() - 7 * 86_400_000);
if (date >= startOfToday) return "Today";
if (date >= startOfYesterday) return "Yesterday";
if (date >= startOf7DaysAgo) return "Previous 7 days";
return "Older";
}
interface SessionItem {
id: string;
title: string;
created_at: string;
}
interface SessionGroup {
label: string;
sessions: SessionItem[];
}
/**
* Group a flat list of sessions (already sorted newest-first) into date-labeled groups.
*/
export function groupSessionsByDate(sessions: SessionItem[]): SessionGroup[] {
const groups: SessionGroup[] = [];
let current: SessionGroup | undefined;
for (const s of sessions) {
const label = dateLabel(s.created_at);
if (!current || current.label !== label) {
current = { label, sessions: [] };
groups.push(current);
}
current.sessions.push(s);
}
return groups;
}