Skip to content

Instantly share code, notes, and snippets.

@ststeiger
Last active April 22, 2025 12:47
Show Gist options
  • Save ststeiger/3168d9dcedbfc1ae7115475c54195321 to your computer and use it in GitHub Desktop.
Save ststeiger/3168d9dcedbfc1ae7115475c54195321 to your computer and use it in GitHub Desktop.
How to properly format file-size in JS
enum ByteFormatMode {
Binary, // 1024-based (KiB, MiB, GiB - IEC standard)
Decimal, // 1000-based (KB, MB, GB - SI standard)
Pseudo // 1024-based but uses KB/MB/GB (Windows-style)
}
function formatBytes(bytes: number, mode: ByteFormatMode = ByteFormatMode.Binary): string {
const suffixesBinary = ["bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"];
const suffixesDecimal = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "RB", "QB"];
const suffixesPseudo = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "RB", "QB"];
if (bytes === 0) return "0 bytes";
if (bytes < 0) return `-${formatBytes(-bytes, mode)}`;
const suffixes = (mode === ByteFormatMode.Decimal) ? suffixesDecimal : suffixesBinary;
const unit = (mode === ByteFormatMode.Decimal) ? 1000 : 1024;
const unitIndex = Math.floor(Math.log(bytes) / Math.log(unit));
const safeUnitIndex = Math.min(unitIndex, suffixes.length - 1);
const num = Math.round((bytes / Math.pow(unit, safeUnitIndex)) * 10) / 10;
return `${num} ${suffixes[safeUnitIndex]}`;
}
/**
* Formats bytes into a human-readable string with appropriate unit.
* @param {number} bytes - The size in bytes.
* @param {string} mode - "Binary" (IEC), "Decimal" (SI), or "Pseudo" (default: "Binary").
* @returns {string} Formatted string with unit (e.g., "1.5 MiB").
*/
function formatBytes(bytes, mode = "Binary") {
const suffixesBinary = ["bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"];
const suffixesDecimal = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "RB", "QB"];
if (bytes === 0) return "0 bytes";
if (bytes < 0) return "-" + formatBytes(-bytes, mode); // Handle negatives
const suffixes = (mode === "Decimal") ? suffixesDecimal : suffixesBinary;
const unit = (mode === "Decimal") ? 1000 : 1024;
// Calculate the appropriate unit index (logarithmic scale)
const unitIndex = Math.floor(Math.log(bytes) / Math.log(unit));
const safeUnitIndex = Math.min(unitIndex, suffixes.length - 1); // Prevent overflow
// Round to 1 decimal place
const num = Math.round(bytes / Math.pow(unit, safeUnitIndex) * 10) / 10;
return `${num} ${suffixes[safeUnitIndex]}`;
}
function formatInteger(number) {
return number.toLocaleString('en-US').replace(/,/g, "'");
}
// Example usage:
console.log(formatInteger(1234567)); // Output: 1'234'567
function formatFloat(number, decimalPlaces = 2) {
return number.toLocaleString('en-US', {
minimumFractionDigits: decimalPlaces,
maximumFractionDigits: decimalPlaces
}).replace(/,/g, "'");
}
// Example usage:
console.log(formatFloat(1234567.89123)); // Output: 1'234'567.89
console.log(formatFloat(1234567.89123, 5)); // Output: 1'234'567.89123
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment