// Copyright Epic Games, Inc. All Rights Reserved. "use strict"; //////////////////////////////////////////////////////////////////////////////// export class Friendly { static sep(value, prec=0) { return (+Number(value)).toLocaleString("en", { style: "decimal", minimumFractionDigits : prec, maximumFractionDigits : prec, }); } static k(x, p=0) { return Friendly.sep((BigInt(x) + 999n) / BigInt(Math.pow(10, 3))|0n, p) + "K"; } static m(x, p=1) { return Friendly.sep( BigInt(x) / BigInt(Math.pow(10, 6)), p) + "M"; } static g(x, p=2) { return Friendly.sep( BigInt(x) / BigInt(Math.pow(10, 9)), p) + "G"; } static kib(x, p=0) { return Friendly.sep((BigInt(x) + 1023n) / (1n << 10n)|0n, p) + " KiB"; } static mib(x, p=1) { return Friendly.sep( BigInt(x) / (1n << 20n), p) + " MiB"; } static gib(x, p=2) { return Friendly.sep( BigInt(x) / (1n << 30n), p) + " GiB"; } static duration(s) { const v = Number(s); if (v >= 1) return Friendly.sep(v, 2) + " s"; if (v >= 0.001) return Friendly.sep(v * 1000, 2) + " ms"; if (v >= 0.000001) return Friendly.sep(v * 1000000, 1) + " µs"; return Friendly.sep(v * 1000000000, 0) + " ns"; } /** Format a .NET-style TimeSpan string (e.g. "0:05:23.4560000") as a human-readable duration. */ static timespan(value) { if (typeof value === "number") { return Friendly._formatDurationMs(value); } const str = String(value); const match = str.match(/^[+-]?(?:(\d+)\.)?(\d+):(\d+):(\d+)(?:\.(\d+))?$/); if (!match) { return str; } const days = parseInt(match[1] || "0", 10); const hours = parseInt(match[2], 10); const minutes = parseInt(match[3], 10); const seconds = parseInt(match[4], 10); const frac = match[5] ? parseInt(match[5].substring(0, 3).padEnd(3, "0"), 10) : 0; const totalMs = ((days * 86400 + hours * 3600 + minutes * 60 + seconds) * 1000) + frac; return Friendly._formatDurationMs(totalMs); } static _formatDurationMs(ms) { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`; if (hours > 0) return `${hours}h ${minutes % 60}m`; if (minutes > 0) return `${minutes}m ${seconds % 60}s`; if (seconds > 0) return `${seconds}.${String(ms % 1000).padStart(3, "0")}s`; return `${ms}ms`; } /** Format an ISO / .NET datetime string as a friendly local date+time. */ static datetime(value) { const d = new Date(value); if (isNaN(d.getTime())) { return String(value); } return d.toLocaleString(undefined, { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit", }); } static bytes(x) { const v = BigInt(Math.trunc(Number(x))); if (v >= (1n << 60n)) return Friendly.sep(Number(v) / Number(1n << 60n), 2) + " EiB"; if (v >= (1n << 50n)) return Friendly.sep(Number(v) / Number(1n << 50n), 2) + " PiB"; if (v >= (1n << 40n)) return Friendly.sep(Number(v) / Number(1n << 40n), 2) + " TiB"; if (v >= (1n << 30n)) return Friendly.sep(Number(v) / Number(1n << 30n), 2) + " GiB"; if (v >= (1n << 20n)) return Friendly.sep(Number(v) / Number(1n << 20n), 1) + " MiB"; if (v >= (1n << 10n)) return Friendly.sep(Number(v) / Number(1n << 10n), 0) + " KiB"; return Friendly.sep(Number(v), 0) + " B"; } }