mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-03 11:54:06 +00:00
perf: cache log timestamp formatters
This commit is contained in:
@@ -1,10 +1,21 @@
|
||||
const validTimeZoneCache = new Map<string, boolean>();
|
||||
const timestampFormatterCache = new Map<string, Intl.DateTimeFormat>();
|
||||
let hostTimeZone: string | undefined;
|
||||
|
||||
export function isValidTimeZone(tz: string): boolean {
|
||||
const cached = validTimeZoneCache.get(tz);
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
}
|
||||
let valid = false;
|
||||
try {
|
||||
new Intl.DateTimeFormat("en", { timeZone: tz }).format();
|
||||
return true;
|
||||
valid = true;
|
||||
} catch {
|
||||
return false;
|
||||
valid = false;
|
||||
}
|
||||
validTimeZoneCache.set(tz, valid);
|
||||
return valid;
|
||||
}
|
||||
|
||||
type TimestampStyle = "short" | "medium" | "long";
|
||||
@@ -18,7 +29,7 @@ function resolveEffectiveTimeZone(timeZone?: string): string {
|
||||
const explicit = timeZone ?? process.env.TZ;
|
||||
return explicit && isValidTimeZone(explicit)
|
||||
? explicit
|
||||
: Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
: (hostTimeZone ??= Intl.DateTimeFormat().resolvedOptions().timeZone);
|
||||
}
|
||||
|
||||
function formatOffset(offsetRaw: string): string {
|
||||
@@ -26,18 +37,25 @@ function formatOffset(offsetRaw: string): string {
|
||||
}
|
||||
|
||||
function getTimestampParts(date: Date, timeZone?: string) {
|
||||
const fmt = new Intl.DateTimeFormat("en", {
|
||||
timeZone: resolveEffectiveTimeZone(timeZone),
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
hour12: false,
|
||||
fractionalSecondDigits: 3 as 1 | 2 | 3,
|
||||
timeZoneName: "longOffset",
|
||||
});
|
||||
const effectiveTimeZone = resolveEffectiveTimeZone(timeZone);
|
||||
let fmt = timestampFormatterCache.get(effectiveTimeZone);
|
||||
if (!fmt) {
|
||||
// Log timestamps are formatted on hot paths; Intl construction is much
|
||||
// costlier than formatToParts, while timezone rules remain process-stable.
|
||||
fmt = new Intl.DateTimeFormat("en", {
|
||||
timeZone: effectiveTimeZone,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
hour12: false,
|
||||
fractionalSecondDigits: 3 as 1 | 2 | 3,
|
||||
timeZoneName: "longOffset",
|
||||
});
|
||||
timestampFormatterCache.set(effectiveTimeZone, fmt);
|
||||
}
|
||||
|
||||
const parts = Object.fromEntries(fmt.formatToParts(date).map((part) => [part.type, part.value]));
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user