How can I pad a value with leading zeros?

Viewed 298061

What is the recommended way to zerofill a value in JavaScript? I imagine I could build a custom function to pad zeros on to a typecasted value, but I'm wondering if there is a more direct way to do this?

Note: By "zerofilled" I mean it in the database sense of the word (where a 6-digit zerofilled representation of the number 5 would be "000005").

77 Answers

Simple way. You could add string multiplication for the pad and turn it into a function.

var pad = "000000";
var n = '5';
var result = (pad+n).slice(-pad.length);

As a function,

function paddy(num, padlen, padchar) {
    var pad_char = typeof padchar !== 'undefined' ? padchar : '0';
    var pad = new Array(1 + padlen).join(pad_char);
    return (pad + num).slice(-pad.length);
}
var fu = paddy(14, 5); // 00014
var bar = paddy(2, 4, '#'); // ###2

Since ECMAScript 2017 we have padStart:

const padded = (.1 + "").padStart(6, "0");
console.log(`-${padded}`);

Before ECMAScript 2017

With toLocaleString:

var n=-0.1;
var res = n.toLocaleString('en', {minimumIntegerDigits:4,minimumFractionDigits:2,useGrouping:false});
console.log(res);

I actually had to come up with something like this recently. I figured there had to be a way to do it without using loops.

This is what I came up with.

function zeroPad(num, numZeros) {
    var n = Math.abs(num);
    var zeros = Math.max(0, numZeros - Math.floor(n).toString().length );
    var zeroString = Math.pow(10,zeros).toString().substr(1);
    if( num < 0 ) {
        zeroString = '-' + zeroString;
    }

    return zeroString+n;
}

Then just use it providing a number to zero pad:

> zeroPad(50,4);
"0050"

If the number is larger than the padding, the number will expand beyond the padding:

> zeroPad(51234, 3);
"51234"

Decimals are fine too!

> zeroPad(51.1234, 4);
"0051.1234"

If you don't mind polluting the global namespace you can add it to Number directly:

Number.prototype.leftZeroPad = function(numZeros) {
    var n = Math.abs(this);
    var zeros = Math.max(0, numZeros - Math.floor(n).toString().length );
    var zeroString = Math.pow(10,zeros).toString().substr(1);
    if( this < 0 ) {
        zeroString = '-' + zeroString;
    }

    return zeroString+n;
}

And if you'd rather have decimals take up space in the padding:

Number.prototype.leftZeroPad = function(numZeros) {
    var n = Math.abs(this);
    var zeros = Math.max(0, numZeros - n.toString().length );
    var zeroString = Math.pow(10,zeros).toString().substr(1);
    if( this < 0 ) {
        zeroString = '-' + zeroString;
    }

    return zeroString+n;
}

Cheers!



XDR came up with a logarithmic variation that seems to perform better.

WARNING: This function fails if num equals zero (e.g. zeropad(0, 2))

function zeroPad (num, numZeros) {
    var an = Math.abs (num);
    var digitCount = 1 + Math.floor (Math.log (an) / Math.LN10);
    if (digitCount >= numZeros) {
        return num;
    }
    var zeroString = Math.pow (10, numZeros - digitCount).toString ().substr (1);
    return num < 0 ? '-' + zeroString + an : zeroString + an;
}

Speaking of performance, tomsmeding compared the top 3 answers (4 with the log variation). Guess which one majorly outperformed the other two? :)

Here's a quick function I came up with to do the job. If anyone has a simpler approach, feel free to share!

function zerofill(number, length) {
    // Setup
    var result = number.toString();
    var pad = length - result.length;

    while(pad > 0) {
        result = '0' + result;
        pad--;
    }

    return result;
}

With ES6+ JavaScript:

You can "zerofill a number" with something like the following function:

/**
 * @param number The number
 * @param minLength Minimal length for your string with leading zeroes
 * @return Your formatted string
 */
function zerofill(nb, minLength) {
    // Convert your number to string.
    let nb2Str = nb.toString()

    // Guess the number of zeroes you will have to write.
    let nbZeroes = Math.max(0, minLength - nb2Str.length)

    // Compute your result.
    return `${ '0'.repeat(nbZeroes) }${ nb2Str }`
}

console.log(zerofill(5, 6))    // Displays "000005"

With ES2017+:

/**
 * @param number The number
 * @param minLength Minimal length for your string with leading zeroes
 * @return Your formatted string
 */
const zerofill = (nb, minLength) => nb.toString().padStart(minLength, '0')

console.log(zerofill(5, 6))    // Displays "000005"

If performance is really critical (looping over millions of records), an array of padding strings can be pre-generated, avoiding to do it for each call.

Time complexity: O(1).
Space complexity: O(1).

const zeroPads = Array.from({ length: 10 }, (_, v) => '0'.repeat(v))

function zeroPad(num, len) {
  const numStr = String(num)
  return (zeroPads[len - numStr.length] + numStr)
}

I didn't see any answer in this form so here my shot with regex and string manipulation

(Works also for negative and decimal numbers)

Code:

function fillZeroes(n = 0, m = 1) {
  const p = Math.max(1, m);
  return String(n).replace(/\d+/, x => '0'.repeat(Math.max(p - x.length, 0)) + x);
}

Some outputs:

console.log(fillZeroes(6, 2))          // >> '06'
console.log(fillZeroes(1.35, 2))       // >> '01.35'
console.log(fillZeroes(-16, 3))        // >> '-016'
console.log(fillZeroes(-1.456, 3))     // >> '-001.456'
console.log(fillZeroes(-456.53453, 6)) // >> '-000456.53453'
console.log(fillZeroes('Agent 7', 3))  // >> 'Agent 007'

A silly recursive way is:

function paddingZeros(text, limit) {
  if (text.length < limit) {
    return paddingZeros("0" + text, limit);
  } else {
    return text;
  }
}

where the limit is the size you want the string to be.

Ex: appendZeros("7829", 20) // 00000000000000007829

A simple short recursive function to achieve your proposal:

function padleft (YourNumber, OutputLength){
    if (YourNumber.length >= OutputLength) {
        return YourNumber;
    } else {
        return padleft("0" +YourNumber, OutputLength);
    }
}
  • YourNumber is the input number.
  • OutputLength is the preferred output number length (with 0 padding left).

This function will add 0 on the left if your input number length is shorter than the wanted output number length.

I have 2 solutions. The first is the real basic one to bad a number with zeros if you know that's all you want to do quickly.

The second will also pad negative numbers - same as the "clever" solution that seems to have the best answer score.

Here goes:

// One liner simple mode!
// (always ensure the number is 6 digits long knowing its never negative)
var mynum = 12;
var mynum2 = "0".repeat((n=6-mynum.toString().length)>0?n:0)+mynum;
alert("One liner to pad number to be 6 digits long = Was "+mynum+" Now "+mynum2);

// As a function which will also pad negative numbers
// Yes, i could do a check to only take "-" into account
// if it was passed in as an integer and not a string but
// for this, i haven't.
// 
// @s The string or integer to pad
// @l The minumum length of @s
// @c The character to pad with
// @return updated string
function padme(s,l,c){
    s = s.toString();
    c = c.toString();
    m = s.substr(0,1)=="-";
    return (m?"-":"")+c.repeat((n=l-(s.length-(m?1:0)))>0?n:0)+s.substr((m?1:0));
}
alert("pad -12 to ensure it is 8 digits long = "+padme(-12,8,0));
alert("pad 'hello' with 'x' to ensure it is 12 digits long = "+padme('hello',12,'x'));

A simple elegant solution, where n is the number and l is the length.

function nFill (n, l) {return (l>n.toString().length)?((Array(l).join('0')+n).slice(-l)):n;}

This keeps the length if it is over desired, as not to alter the number.

n = 500;

console.log(nFill(n, 5));
console.log(nFill(n, 2));

function nFill (n, l) {return (l>n.toString().length)?((Array(l).join('0')+n).slice(-l)):n;}

The following provides a quick and fast solution:

function numberPadLeft(num , max, padder = "0"){
     return "" == (num += "") ? "" :
     ( dif = max - num.length, dif > 0 ?
     padder.repeat(dif < 0 ? 0 : dif) + num :
     num )
}

I came up with an absurd one-liner while writing a numeric base converter. Didn't see anything quite like it in the other answers, so here goes:

// This is cursed
function p(i,w,z){z=z||0;w=w||8;i+='';var o=i.length%w;return o?[...Array(w-o).fill(z),...i].join(''):i;}

console.log(p(8675309));        // Default: pad w/ 0 to 8 digits
console.log(p(525600, 10));     // Pad to 10 digits
console.log(p(69420, 10, 'X')); // Pad w/ X to 10 digits
console.log(p(8675309, 4));     // Pad to next 4 digits
console.log(p(12345678));       // Don't pad if you ain't gotta pad

Or, in a form that doesn't quite as readily betray that I've sold my soul to the Black Perl:

function pad(input, width, zero) {
    zero = zero || 0; width = width || 8;  // Defaults
    input += '';                           // Convert input to string first
    
    var overflow = input.length % width    // Do we overflow?
    if (overflow) {                        // Yep!  Let's pad it...
        var needed = width - overflow;     // ...to the next boundary...
        var zeroes = Array(needed);        // ...with an array...
        zeroes = zeroes.fill(zero);        // ...full of our zero character...
        var output = [...zeroes,...input]; // ...and concat those zeroes to input...
        output = output.join('');          // ...and finally stringify.
    } else {
        var output = input;                // We don't overflow; no action needed :)
    }
    
    return output;                         // Done!
}

One thing that sets this apart from the other answers is that it takes a modulo of the number's length to the target width rather than a simple greater-than check. This is handy if you want to make sure the resulting length is some multiple of a target width (e.g. you need the output to be either 5 or 10 characters long).

No idea how well it performs, but hey, at least it's already minified!

Here's a little trick I think is cool:

(2/10000).toString().split(".")[1]
"0002"
(52/10000).toString().split(".")[1]
"0052"

Posting in case this is what you are looking for, converts time remaining in milliseconds to a string like 00:04:21

function showTimeRemaining(remain){
  minute = 60 * 1000;
  hour = 60 * minute;
  //
  hrs = Math.floor(remain / hour);
  remain -= hrs * hour;
  mins = Math.floor(remain / minute);
  remain -= mins * minute;
  secs = Math.floor(remain / 1000);
  timeRemaining = hrs.toString().padStart(2, '0') + ":" + mins.toString().padStart(2, '0') + ":" + secs.toString().padStart(2, '0');
  return timeRemaining;
}

I found the problem interesting, I put my small contribution

function zeroLeftComplete(value, totalCharters = 3) {
    const valueString = value.toString() || '0'
    const zeroLength = valueString.length - totalCharters
    if (Math.sign(parseInt(zeroLength)) === -1) {
        const zeroMissing = Array.from({ length: Math.abs(zeroLength) }, () => '0').join('')
        return `${zeroMissing}${valueString}`
    } else return valueString

};
console.log(zeroLeftComplete(0));
console.log(zeroLeftComplete(1));
console.log(zeroLeftComplete(50));
console.log(zeroLeftComplete(50561,3));

Related