Files
HealthLog/src/lib/intl/formatter-cache.ts
T
Marc-André Bombeck 146fcac079 chore: write NUL as an escape instead of a raw byte
Raw NUL bytes in source files make grep and ripgrep treat the file as
binary and skip it, so sweeps silently miss it. The affected string and
regex literals use the escape now; behaviour is unchanged.
2026-10-19 14:57:00 +02:00

45 lines
1.6 KiB
TypeScript

/**
* Process-wide cache for `Intl.NumberFormat` / `Intl.DateTimeFormat`
* instances, keyed by locale + options.
*
* Constructing an `Intl.*` formatter is comparatively expensive; several
* list-item helpers built one per row per render (`workout-list`,
* `recent-workouts-tile`, `medication-card`, …). These getters return a cached
* instance so the construction cost is paid once per distinct (locale, options)
* shape instead of once per call. Formatters are immutable + stateless, so
* sharing a single instance across calls is safe.
*
* Keyed by `locale + "\u0000" + JSON.stringify(options)`; stringifying the
* (tiny, literal) options object per call is orders of magnitude cheaper than
* a formatter construction. The set of distinct shapes is bounded and small,
* so the cache never needs eviction.
*/
const numberFormatters = new Map<string, Intl.NumberFormat>();
const dateTimeFormatters = new Map<string, Intl.DateTimeFormat>();
export function getNumberFormat(
locale: string,
options: Intl.NumberFormatOptions,
): Intl.NumberFormat {
const key = `${locale}\u0000${JSON.stringify(options)}`;
let fmt = numberFormatters.get(key);
if (!fmt) {
fmt = new Intl.NumberFormat(locale, options);
numberFormatters.set(key, fmt);
}
return fmt;
}
export function getDateTimeFormat(
locale: string,
options: Intl.DateTimeFormatOptions,
): Intl.DateTimeFormat {
const key = `${locale}\u0000${JSON.stringify(options)}`;
let fmt = dateTimeFormatters.get(key);
if (!fmt) {
fmt = new Intl.DateTimeFormat(locale, options);
dateTimeFormatters.set(key, fmt);
}
return fmt;
}