Skip to content

Instantly share code, notes, and snippets.

@cheton
Last active June 29, 2018 07:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cheton/3913d1fc75c10110a8d7ea310bcd2e18 to your computer and use it in GitHub Desktop.
Save cheton/3913d1fc75c10110a8d7ea310bcd2e18 to your computer and use it in GitHub Desktop.
Converts bytes into human readable size units.
const units = [
'B',
'KB',
'MB',
'GB',
'TB',
'PB',
'EB',
'ZB',
'YB',
];
const defaults = {
separator: {
thousands: ',',
decimal: '.',
},
output: 'string',
format: '{{size}} {{unit}}',
};
const readableSize = (value, options) => {
const {
separator = false,
format = defaults.format,
output = defaults.output,
} = { ...options };
if (!Number.isInteger(value)) {
throw new TypeError(`"value" must be an integer: ${value}`);
}
if (value > Number.MAX_SAFE_INTEGER) {
// The largest exact integral value is 2^53 - 1, or 9007199254740991.
// In ES6, this is defined as Number.MAX_SAFE_INTEGER.
throw new Error(`"value" exceeds the integer range (${Number.MAX_SAFE_INTEGER}): ${value}`);
}
if (value < 0) {
throw new TypeError(`"value" is invalid: ${value}`);
}
let size = String(value);
let unit = units[0];
if (value >= 1024) {
let u = Math.floor(Math.log(value) / Math.log(1024));
if (u >= units.length) {
u = units.length - 1;
}
size = value / Math.pow(1024, u);
if (((u + 1) < units.length) && size >= 1000) {
size /= 1024;
++u;
}
if (size >= 100 || u === 0) {
size = String((Math.floor(size * 1) / 1).toFixed(0));
} else if (size >= 10) {
size = String((Math.floor(size * 10) / 10).toFixed(1));
} else {
size = String((Math.floor(size * 100) / 100).toFixed(2));
}
unit = units[u];
}
if (typeof separator === 'object' || separator === true) {
const {
thousands = defaults.separator.thousands,
decimal = defaults.separator.decimal,
} = { ...separator };
const parts = size.split(defaults.separator.decimal);
if (thousands && parts[0] && parts[0].length > 3) {
parts[0] = parts[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, thousands);
}
if (decimal) {
size = parts.join(decimal);
} else {
size = parts.join(defaults.separator.decimal);
}
}
if (output === 'array') {
return [size, unit];
}
if (output === 'object') {
return { size, unit };
}
return (typeof format === 'function')
? format({ size, unit })
: String(format).replace('{{size}}', size).replace('{{unit}}', unit);
};
export default readableSize;
@cheton
Copy link
Author

cheton commented Jun 28, 2018

Expected Result

readableSize(0); // '0 B'
readableSize(1); // '1 B'
readableSize(999); // '999 B'
readableSize(1000); // '1000 B'
readableSize(1001); // '1001 B'
readableSize(1023); // '1023 B'
readableSize(1024); // '1.00 KB'
readableSize(1025); // '1.00 KB'
readableSize(999999); // '976 KB'
readableSize(1000000); // '976 KB'
readableSize(1000001); // '976 KB'
readableSize(1023999); // '999 KB'
readableSize(1024000); // '0.97 MB'
readableSize(1024001); // '0.97 MB'
readableSize(1048575); // '0.99 MB'
readableSize(1048576); // '1.00 MB'
readableSize(1048577); // '1.00 MB'
readableSize(999999999); // '953 MB'
readableSize(1000000000); // '953 MB'
readableSize(1000000001); // '953 MB'
readableSize(1048575999); // '999 MB'
readableSize(1048576000); // '0.97 GB'
readableSize(1048576001); // '0.97 GB'
readableSize(1073741823); // '0.99 GB'
readableSize(1073741824); // '1.00 GB'
readableSize(1073741825); // '1.00 GB'
readableSize(999999999999); // '931 GB'
readableSize(1000000000000); // '931 GB'
readableSize(1000000000001); // '931 GB'
readableSize(1073741823999); // '999 GB'
readableSize(1073741824000); // '0.97 TB'
readableSize(1073741824001); // '0.97 TB'
readableSize(1099511627775); // '0.99 TB'
readableSize(1099511627776); // '1.00 TB'
readableSize(1099511627777); // '1.00 TB'
readableSize(999999999999999); // '909 TB'
readableSize(1000000000000000); // '909 TB'
readableSize(1000000000000001); // '909 TB'
readableSize(1099511627775999); // '999 TB'
readableSize(1099511627776000); // '0.97 PB'
readableSize(1099511627776001); // '0.97 PB'
readableSize(1125899906842623); // '0.99 PB'
readableSize(1125899906842624); // '1.00 PB'
readableSize(1125899906842625); // '1.00 PB'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment