Files
ProxLedger/src/lib/format.ts
T
florian.wildeandClaude Opus 5 8596a18a27 feat(ui): klickbarer Prototyp mit Beispieldaten (#002)
Layout im AdminLTE-Stil (Sidebar, Kopfleiste, Inhaltskopf, Footer), Logo als
SVG-Komponente, Farbschema mit Dark-Mode, Dashboard, Kunden- und Host-Ansichten,
Rechnungsuebersicht, Jahresbahn und globale Suche (Strg+K).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 20:03:15 +02:00

78 lines
2.6 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.
/** Deutsche Formatierung für Datum, Währung und Zahlen. Anzeige-Zeitzone: Europe/Berlin. */
const ZEITZONE = "Europe/Berlin";
const datumFormat = new Intl.DateTimeFormat("de-DE", {
timeZone: ZEITZONE,
day: "2-digit",
month: "2-digit",
year: "numeric",
});
const datumZeitFormat = new Intl.DateTimeFormat("de-DE", {
timeZone: ZEITZONE,
day: "2-digit",
month: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
});
const waehrungFormat = new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" });
export function formatDatum(wert: string | Date | null | undefined): string {
if (!wert) return "–";
return datumFormat.format(new Date(wert));
}
export function formatDatumZeit(wert: string | Date | null | undefined): string {
if (!wert) return "–";
return `${datumZeitFormat.format(new Date(wert))} Uhr`;
}
export function formatEuro(betrag: number | null | undefined): string {
if (betrag === null || betrag === undefined) return "–";
return waehrungFormat.format(betrag);
}
export function formatZahl(wert: number | null | undefined): string {
if (wert === null || wert === undefined) return "–";
return new Intl.NumberFormat("de-DE").format(wert);
}
/** Ganze Tage zwischen heute und einem Datum; negativ, wenn das Datum in der Vergangenheit liegt. */
export function tageBis(datum: string | Date | null | undefined, heute: Date): number | null {
if (!datum) return null;
const tagMs = 24 * 60 * 60 * 1000;
const ziel = Date.UTC(
new Date(datum).getUTCFullYear(),
new Date(datum).getUTCMonth(),
new Date(datum).getUTCDate(),
);
const start = Date.UTC(heute.getUTCFullYear(), heute.getUTCMonth(), heute.getUTCDate());
return Math.round((ziel - start) / tagMs);
}
export function formatTageBis(tage: number | null): string {
if (tage === null) return "–";
if (tage === 0) return "heute";
if (tage === 1) return "in 1 Tag";
if (tage > 1) return `in ${tage} Tagen`;
if (tage === -1) return "seit 1 Tag";
return `seit ${Math.abs(tage)} Tagen`;
}
export function formatUptime(sekunden: number | null | undefined): string {
if (sekunden === null || sekunden === undefined) return "–";
const tage = Math.floor(sekunden / 86400);
const stunden = Math.floor((sekunden % 86400) / 3600);
if (tage > 0) return `${formatZahl(tage)} Tage, ${stunden} h`;
return `${stunden} h`;
}
/** Stunden seit einem Zeitpunkt, für die Regel „keine Meldung seit 48 h“. */
export function stundenSeit(zeitpunkt: string | Date | null | undefined, jetzt: Date): number | null {
if (!zeitpunkt) return null;
return (jetzt.getTime() - new Date(zeitpunkt).getTime()) / 3_600_000;
}