Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions apps/mobile/src/relative-date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Relative time for activity timestamps. Values slightly in the future are
* clock skew and still read "Just now"; further future values fall back to a
* date instead of claiming they just happened.
*/
export function relativeDate(value: string, now = Date.now()): string {
const parsed = Date.parse(value);
if (!Number.isFinite(parsed)) return value;
const diff = now - parsed;
if (diff < -60_000) return dayLabel(parsed);
const elapsed = Math.max(0, diff);
if (elapsed < 60_000) return "Just now";
if (elapsed < 3600_000) return `${Math.floor(elapsed / 60_000)}m ago`;
if (elapsed < 86400_000) return `${Math.floor(elapsed / 3600_000)}h ago`;
return dayLabel(parsed);
}

function dayLabel(value: number): string {
return new Date(value).toLocaleDateString("en-US", { month: "short", day: "numeric" });
}
11 changes: 1 addition & 10 deletions apps/mobile/src/ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -446,16 +446,7 @@ export function timeLabel(value: string, timeZone?: string) {
? value
: date.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", timeZone });
}
export function relativeDate(value: string) {
const diff = Date.now() - new Date(value).getTime();
return diff < 60_000
? "Just now"
: diff < 3600_000
? `${Math.floor(diff / 60_000)}m ago`
: diff < 86400_000
? `${Math.floor(diff / 3600_000)}h ago`
: dateLabel(value);
}
export { relativeDate } from "./relative-date";

export function resultSummary(value: string) {
return /^Saved to (?:sample|local) sent mail(?: · .+)?$/.test(value)
Expand Down
24 changes: 24 additions & 0 deletions apps/mobile/test/relative-date.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import assert from "node:assert/strict";
import test from "node:test";
import { relativeDate } from "../src/relative-date.ts";

const now = Date.parse("2026-09-30T12:00:00Z");

test("recent past timestamps keep their buckets", () => {
assert.equal(relativeDate("2026-09-30T11:59:30Z", now), "Just now");
assert.equal(relativeDate("2026-09-30T11:30:00Z", now), "30m ago");
assert.equal(relativeDate("2026-09-30T09:00:00Z", now), "3h ago");
});

test("future timestamps beyond clock skew show a date instead of just now", () => {
assert.equal(relativeDate("2026-09-30T12:00:10Z", now), "Just now");
const expected = new Date(Date.parse("2026-10-05T12:00:00Z")).toLocaleDateString("en-US", {
month: "short",
day: "numeric",
});
assert.equal(relativeDate("2026-10-05T12:00:00Z", now), expected);
});

test("an unparseable timestamp is returned unchanged", () => {
assert.equal(relativeDate("not-a-date", now), "not-a-date");
});