Files
openidea/src/platform/dateFormat.ts
T
l0ng-ai 429e8ffc82 fix(i18n): Translate the remaining Git and pull request text (#116)
Multi-repo branch popup matches actions by their translated label (highlights and Chinese search now work) and translates its group headers. Conflict counts, relative times (shared dateFormat), in-progress operation titles, git operation progress/results, branch widget tooltips, diff/hunk counts, worktree markers, PR author line and review placeholders go through tx; the default "Changes" changelist shows its translated name. HexViewer read-only leaves the untranslated allowlist. 92 zh entries.

Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
2026-10-28 12:38:25 +08:00

82 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Date / time formatting per Settings › System Settings › Date Formats:
* "Override system date and time format" (pattern + 24-hour time) and
* "Use pretty formatting" (Today / Yesterday / N min ago). Used by the Git
* log, Local History, commit details and blame.
*/
import { tx } from "./i18n";
import { useProject } from "./project";
export interface DateFormatOptions {
overrideSystem: boolean;
/** `yyyy`, `yy`, `MMMM`, `MMM`, `MM`, `M`, `dd`, `d` placeholders. */
pattern: string;
use24Hour: boolean;
pretty: boolean;
}
export const DEFAULT_DATE_FORMAT: DateFormatOptions = {
overrideSystem: false,
pattern: "dd.MM.yyyy",
use24Hour: true,
pretty: true,
};
export function dateFormatOptions(): DateFormatOptions {
const raw = useProject.getState().settings?.general?.dateFormat as Partial<DateFormatOptions> | undefined;
return {
overrideSystem: typeof raw?.overrideSystem === "boolean" ? raw.overrideSystem : DEFAULT_DATE_FORMAT.overrideSystem,
pattern: typeof raw?.pattern === "string" && raw.pattern.trim() ? raw.pattern : DEFAULT_DATE_FORMAT.pattern,
use24Hour: typeof raw?.use24Hour === "boolean" ? raw.use24Hour : DEFAULT_DATE_FORMAT.use24Hour,
pretty: typeof raw?.pretty === "boolean" ? raw.pretty : DEFAULT_DATE_FORMAT.pretty,
};
}
const pad = (n: number, w = 2) => String(n).padStart(w, "0");
/** Formats the date part with a `dd.MM.yyyy`-style pattern. */
export function formatPattern(d: Date, pattern: string): string {
const tokens: Record<string, () => string> = {
yyyy: () => String(d.getFullYear()),
yy: () => pad(d.getFullYear() % 100),
MMMM: () => d.toLocaleString("en", { month: "long" }),
MMM: () => d.toLocaleString("en", { month: "short" }),
MM: () => pad(d.getMonth() + 1),
M: () => String(d.getMonth() + 1),
dd: () => pad(d.getDate()),
d: () => String(d.getDate()),
};
return pattern.replace(/yyyy|yy|MMMM|MMM|MM|M|dd|d/g, (m) => tokens[m]!());
}
export function formatClock(d: Date, o: DateFormatOptions = dateFormatOptions()): string {
if (!o.overrideSystem) return d.toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit" });
if (o.use24Hour) return `${pad(d.getHours())}:${pad(d.getMinutes())}`;
const h = d.getHours() % 12 || 12;
return `${h}:${pad(d.getMinutes())} ${d.getHours() < 12 ? "AM" : "PM"}`;
}
/** Date only (blame gutter, compact columns). */
export function formatDay(d: Date, o: DateFormatOptions = dateFormatOptions(), short = false): string {
if (o.overrideSystem) return formatPattern(d, o.pattern);
return short
? d.toLocaleDateString(undefined, { year: "2-digit", month: "2-digit", day: "2-digit" })
: d.toLocaleDateString(undefined, { year: "numeric", month: "short", day: "numeric" });
}
/** Timestamp for lists: pretty ("Today 10:42", "5 min ago") when enabled, else date + time. */
export function formatTimestamp(ms: number, now = Date.now(), o: DateFormatOptions = dateFormatOptions()): string {
const d = new Date(ms);
if (o.pretty) {
const diff = now - ms;
const min = 60_000;
if (diff >= 0 && diff < min) return tx("Moments ago");
if (diff >= 0 && diff < 60 * min) return tx`${Math.floor(diff / min)} min ago`;
const today = new Date(now);
if (d.toDateString() === today.toDateString()) return tx`Today ${formatClock(d, o)}`;
if (d.toDateString() === new Date(now - 86_400_000).toDateString()) return tx`Yesterday ${formatClock(d, o)}`;
return formatDay(d, o);
}
return `${formatDay(d, o)} ${formatClock(d, o)}`;
}