formatBriefTimestamp.ts
utils/formatBriefTimestamp.ts
No strong subsystem tag
82
Lines
2223
Bytes
1
Exports
0
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with general runtime concerns. It contains 82 lines, 0 detected imports, and 1 detected exports.
Important relationships
Detected exports
formatBriefTimestamp
Keywords
localedateposixdaysagonumericformatlocale-dependentlc_alllc_timelang
Detected imports
- No import paths detected.
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
/**
* Format an ISO timestamp for the brief/chat message label line.
*
* Display scales with age (like a messaging app):
* - same day: "1:30 PM" or "13:30" (locale-dependent)
* - within 6 days: "Sunday, 4:15 PM" (locale-dependent)
* - older: "Sunday, Feb 20, 4:30 PM" (locale-dependent)
*
* Respects POSIX locale env vars (LC_ALL > LC_TIME > LANG) for time format
* (12h/24h), weekday names, month names, and overall structure.
* Bun/V8's `toLocaleString(undefined)` ignores these on macOS, so we
* convert them to BCP 47 tags ourselves.
*
* `now` is injectable for tests.
*/
export function formatBriefTimestamp(
isoString: string,
now: Date = new Date(),
): string {
const d = new Date(isoString)
if (Number.isNaN(d.getTime())) {
return ''
}
const locale = getLocale()
const dayDiff = startOfDay(now) - startOfDay(d)
const daysAgo = Math.round(dayDiff / 86_400_000)
if (daysAgo === 0) {
return d.toLocaleTimeString(locale, {
hour: 'numeric',
minute: '2-digit',
})
}
if (daysAgo > 0 && daysAgo < 7) {
return d.toLocaleString(locale, {
weekday: 'long',
hour: 'numeric',
minute: '2-digit',
})
}
return d.toLocaleString(locale, {
weekday: 'long',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit',
})
}
/**
* Derive a BCP 47 locale tag from POSIX env vars.
* LC_ALL > LC_TIME > LANG, falls back to undefined (system default).
* Converts POSIX format (en_GB.UTF-8) to BCP 47 (en-GB).
*/
function getLocale(): string | undefined {
const raw =
process.env.LC_ALL || process.env.LC_TIME || process.env.LANG || ''
if (!raw || raw === 'C' || raw === 'POSIX') {
return undefined
}
// Strip codeset (.UTF-8) and modifier (@euro), replace _ with -
const base = raw.split('.')[0]!.split('@')[0]!
if (!base) {
return undefined
}
const tag = base.replaceAll('_', '-')
// Validate by trying to construct an Intl locale — invalid tags throw
try {
new Intl.DateTimeFormat(tag)
return tag
} catch {
return undefined
}
}
function startOfDay(d: Date): number {
return new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime()
}