Use daemon timestamps for turn timing (#1033)

This commit is contained in:
Mohamed Boudra
2026-05-15 11:09:13 +08:00
committed by GitHub
parent 1962225647
commit a72c7f6c4b
22 changed files with 1284 additions and 193 deletions
+84
View File
@@ -35,3 +35,87 @@ export function formatTimeAgo(date: Date): string {
const day = date.getDate();
return `${month} ${day}`;
}
function isSameLocalDay(a: Date, b: Date): boolean {
return (
a.getFullYear() === b.getFullYear() &&
a.getMonth() === b.getMonth() &&
a.getDate() === b.getDate()
);
}
/**
* Format a chat-message timestamp for hover-revealed UI.
* - Same day: "10:11 PM"
* - Within ~6 days: "Wednesday 10:11 PM"
* - Older: "14 May 2026, 10:11 PM"
*/
export function formatMessageTimestamp(date: Date, now: Date = new Date()): string {
const time = date.toLocaleTimeString(undefined, {
hour: "numeric",
minute: "2-digit",
});
if (isSameLocalDay(date, now)) {
return time;
}
const diffMs = now.getTime() - date.getTime();
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
if (diffDays >= 0 && diffDays < 7) {
const weekday = date.toLocaleDateString(undefined, { weekday: "long" });
return `${weekday} ${time}`;
}
const dateLabel = date.toLocaleDateString(undefined, {
day: "numeric",
month: "short",
year: "numeric",
});
return `${dateLabel}, ${time}`;
}
type DurationFormatMode = "static" | "live";
/**
* Format a duration as a compact human-readable string.
* - Static: integer units only
* - Live: always keep one decimal in the smallest displayed unit
*/
export function formatDuration(
durationMs: number,
options?: { mode?: DurationFormatMode },
): string {
const mode = options?.mode ?? "static";
if (!Number.isFinite(durationMs) || durationMs < 0) {
return mode === "live" ? "0.0s" : "0s";
}
const totalSeconds = durationMs / 1000;
if (mode === "live") {
if (totalSeconds < 60) {
return `${totalSeconds.toFixed(1)}s`;
}
if (totalSeconds < 60 * 60) {
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds - minutes * 60;
return `${minutes}m ${seconds.toFixed(1)}s`;
}
const hours = Math.floor(totalSeconds / (60 * 60));
const minutes = (totalSeconds - hours * 60 * 60) / 60;
return `${hours}h ${minutes.toFixed(1)}m`;
}
const wholeSeconds = Math.floor(totalSeconds);
if (wholeSeconds < 60) {
return `${wholeSeconds}s`;
}
const minutes = Math.floor(wholeSeconds / 60);
if (minutes < 60) {
const seconds = wholeSeconds % 60;
return seconds === 0 ? `${minutes}m` : `${minutes}m ${seconds}s`;
}
const hours = Math.floor(minutes / 60);
const remMinutes = minutes % 60;
return remMinutes === 0 ? `${hours}h` : `${hours}h ${remMinutes}m`;
}