144

I need to generate unique id numbers on the fly using javascript. In the past, I've done this by creating a number using time. The number would be made up of the four digit year, two digit month, two digit day, two digit hour, two digit minute, two digit second, and three digit millisecond. So it would look something like this: 20111104103912732 ... this would give enough certainty of a unique number for my purposes.

It's been a while since I've done this and I don't have the code anymore. Anyone have the code to do this, or have a better suggestion for generating a unique ID?

4

38 Answers 38

150

The shortest way to create a number that you can be pretty sure will be unique among as many separate instances as you can think of is

Date.now() + Math.random()

If there is a 1 millisecond difference in function call, it is 100% guaranteed to generate a different number. For function calls within the same millisecond you should only start to be worried if you are creating more than a few million numbers within this same millisecond, which is not very probable.

For more on the probability of getting a repeated number within the same millisecond see https://stackoverflow.com/a/28220928/4617597

Sign up to request clarification or add additional context in comments.

9 Comments

Also, if you want to keep all the bits of the random number you can generate them separately and merge as strings: new Date().valueOf().toString(36) + Math.random().toString(36).substr(2) That will give you a 19 character alphanumeric string which is a decent amount of entropy. Albeit half of it is predictable.
This should be the accepted answer as when trying other higher voted answers, I got 2 and even 3 times the same value in a row when calling from an async function. This seems to provide enough randomness for a standard 8-core CPU to generate 8 unique strings exactly at the same moment, good enough for my use.
IMHO, the best solution is to use Math.floor(Date.now() * Math.random()). You will do have duplicates if you use only Date.now() in a loop, but Math.random() makes it unique.
I checked on a 1 million item loop and it passed. Pretty unique for me: stackblitz.com/edit/js-unique-id
This approach is used by Universally Unique Lexicographically Sortable Identifiers (ulid) github.com/ulid/spec
|
145

A better approach would be:

new Date().valueOf();

instead of

new Date().getUTCMilliseconds();

valueOf() is "most likely" a unique number. http://www.w3schools.com/jsref/jsref_valueof_date.asp.

4 Comments

It is not a unique number.. milliseconds is not granular enough to be considered unique.
Or simply +new Date()
I just ran a for loop and I got duplicate results with valueOf(). I just use this - +performance.now().toString().replace('.', 7) developer.mozilla.org/en-US/docs/Web/API/Performance/now
@ItzikBenHutta Got 3 times the same value. Using multi-core CPU, probably a race condition with threads.
85

If you just want a unique-ish number, then

var timestamp = new Date().getUTCMilliseconds();

would get you a simple number. But if you need the readable version, you're in for a bit of processing:

var now = new Date();

timestamp = now.getFullYear().toString(); // 2011
timestamp += (now.getMonth < 9 ? '0' : '') + now.getMonth().toString(); // JS months are 0-based, so +1 and pad with 0's
timestamp += ((now.getDate < 10) ? '0' : '') + now.getDate().toString(); // pad with a 0
... etc... with .getHours(), getMinutes(), getSeconds(), getMilliseconds()

11 Comments

@Áxel: I didn't say it's unique, I said it's "unique-ish". of course using a timestamp generated client-side is going to generate dupes.
timestamp should be new Date().getTime(); the date.getUTCMilliseconds() returns a number between 0 and 999. date.getTime() returns milliseconds since 1st Jan. 1970. (normal timestamp). w3schools.com/jsref/jsref_obj_date.asp
-1, since the question was about unique number. First block of code should be omitted entirely.
getUTCMilliseconds The value returned by getUTCMilliseconds() is an integer between 0 and 999.. This is the worst idea for unique id, first paragraph should be removed.
(Math.random().toString().replace('.',Math.random().toString().replace('.',''))) this will give unique number even inside fast loop
|
27

Here's what I do when I want something smaller than a bunch of numbers - change base.

var uid = (new Date().getTime()).toString(36)

3 Comments

@blushrt true, it can cause rare clashes. You could md5 the timestamp using something like code.google.com/p/crypto-js, but for my purposes it was "unique enough", and more importantly, faster.
@frumbert, it depends. MD5 isn't collision resistant either. But in your case I got into trouble very fast because of toString(36) which I assume converts numerical value to it's ascii representation, not sure though, but i can see the problem, if you call your uuid generator often enough, only last 3 chars are changing so the chances are high that you will get into a collision. You get much better odds if you just stick to new Date.getTime() calls. But hey if it worked for your purposes, no problem, i needed it for some unique ids only for my client side code, ended up using uuid node lib.
I love this one! I've adjusted it to (Date.now() + Math.random()).toString(36) to prevent millisecond clashes. It's short and generates something like "k92g5pux.i36"
19

I use

Math.floor(new Date().valueOf() * Math.random())

So if by any chance the code is fired at the same time there is also a teeny chance that the random numbers will be the same.

2 Comments

Not sure new Date() is useful tough. You could get the same numbers with two different dates
I mean, how is it better than simply doing Math.random()?
19

In 2024, you can use the in-browser Crypto API to generate cryptographically strong random values.

function getRandomNumbers() {
  const typedArray = new Uint8Array(10);
  const randomValues = window.crypto.getRandomValues(typedArray);
  return randomValues.join('');
}

console.log(getRandomNumbers());
// 1857488137147725264738

function getRandomNumbers() {
  const typedArray = new Uint8Array(10);
  const randomValues = window.crypto.getRandomValues(typedArray);
  return randomValues.join('');
}

console.log(getRandomNumbers());

both Uint8Array constructor and Crypto.getRandomValues are supported on all major browsers, including IE11

1 Comment

only work with ssl connection, so it can cause issues with local http connection
17

This performs faster than creating a Date instance, uses less code and will always produce a unique number (locally):

function uniqueNumber() {
    var date = Date.now();

    // If created at same millisecond as previous
    if (date <= uniqueNumber.previous) {
        date = ++uniqueNumber.previous;
    } else {
        uniqueNumber.previous = date;
    }

    return date;
}

uniqueNumber.previous = 0;

jsfiddle: http://jsfiddle.net/j8aLocan/

I've released this on Bower and npm: https://github.com/stevenvachon/unique-number

You could also use something more elaborate such as cuid, puid or shortid to generate a non-number.

5 Comments

It seems to me that adding the random numbers would actually make it LESS full proof. With just the time stamp, two numbers would have to be created at the exact same millisecond to be the same. By adding two random numbers, you've now created many combinations of numbers, due to math, that could end up with the same result when multiplied. I know it's unlikely, but ... isn't that right?
Hmm, yes. Perhaps a combination of My answer and abarber's answer would be best.
Good effort, not trying to pick on your answer... but this new solution doesn't actually solve the "more than one id created at the same millisecond" issue because, ya know .. it's javascript, on the CLIENT side. If a different user created a number at the same exact millisecond , it wouldn't be reflected in uniqueNumber.previous of the 'other' user. Unless you store it on the server somewhere and check for uniqueness... there's just no way that a purely js-based solution like this can be certain it is creating a unique number.
Well, that would be a more elaborate system than just a unique number.
I like this as a simple locally unique id generator. Quick and easy. I've combined it with @frumbert's solution of base36ing it.
10

This should do :

var uniqueNumber = new Date().getTime(); // milliseconds since 1st Jan. 1970

2 Comments

Useful for many cases, eventough this does not really generate pure "unique" ids, in case this function is called multiple times in the same millisecond... But anyway, for user and UI interaction, that's good.
this should be the accepted answer. Lots of irrelevant crap which is difficult and unnecessary, and this answer gives unique time per each millisecond.
9

if you want a unique number after few mili seconds then use Date.now(), if you want to use it inside a for loop then use Date.now() and Math.random() together

unique number inside a for loop

function getUniqueID(){
    for(var i = 0; i< 5; i++)
      console.log(Date.now() + ( (Math.random()*100000).toFixed()))
}
getUniqueID()

output:: all numbers are unique

15598251485988384 155982514859810330 155982514859860737 155982514859882244 155982514859883316

unique number without Math.random()

function getUniqueID(){
        for(var i = 0; i< 5; i++)
          console.log(Date.now())
    }
    getUniqueID()

output:: Numbers are repeated

1559825328327 1559825328327 1559825328327 1559825328328 1559825328328

Comments

5

From investigating online I came up with the following object that creates a unique id per session:

        window.mwUnique ={
        prevTimeId : 0,
        prevUniqueId : 0,
        getUniqueID : function(){
            try {
                var d=new Date();
                var newUniqueId = d.getTime();
                if (newUniqueId == mwUnique.prevTimeId)
                    mwUnique.prevUniqueId = mwUnique.prevUniqueId + 1;
                else {
                    mwUnique.prevTimeId = newUniqueId;
                    mwUnique.prevUniqueId = 0;
                }
                newUniqueId = newUniqueId + '' + mwUnique.prevUniqueId;
                return newUniqueId;                     
            }
            catch(e) {
                mwTool.logError('mwUnique.getUniqueID error:' + e.message + '.');
            }
        }            
    }

It maybe helpful to some people.

Cheers

Andrew

1 Comment

this is the simplest and error proof solution to date about this question. I have tried a different solution (see below), but I have still some concerns about it that need further development.
4

This also should do:

(function() {
    var uniquePrevious = 0;
    uniqueId = function() {
        return uniquePrevious++;
    };
}());

1 Comment

Very similar implementation you can find in lodash UniqueId function, for me, your solution is simple and clean.
4

In ES6:

const ID_LENGTH = 36
const START_LETTERS_ASCII = 97 // Use 64 for uppercase
const ALPHABET_LENGTH = 26

const uniqueID = () => [...new Array(ID_LENGTH)]
  .map(() => String.fromCharCode(START_LETTERS_ASCII + Math.random() * ALPHABET_LENGTH))
 .join('')

Example:

 > uniqueID()
 > "bxppcnanpuxzpyewttifptbklkurvvetigra"

1 Comment

if unique ID is what you want just do btoa(Date())
4

Always get unique Id in JS

function getUniqueId(){
   return (new Date().getTime()).toString(36) + new Date().getUTCMilliseconds();
}

getUniqueId()    // Call the function

------------results like

//"ka2high4264"

//"ka2hj115905"

//"ka2hj1my690"

//"ka2hj23j287"

//"ka2hj2jp869"

1 Comment

This will not give truly unique value, try this code with this [1,2,3,5,6,7,8,9,10].map(item => getUniqueId());
3

Updated for 2021, numbers and ids are not guaranteed to be unique but should be satisfactory unique enough:

(oh, and who knew something.toString(36) is even a thing 🙂)

// a pseudo-random floating number based on Date.now()
const generateRandomNumber = () =>
  Math.log2(Date.now()) + Math.random();

console.log("a pseudo-random floating number based on Date.now():");
console.log(generateRandomNumber());

// a locally unique-ish HTML id
const generateUniqueId = () => `_${Date.now().toString(36)}${Math.floor(Number.MAX_SAFE_INTEGER * Math.random()).toString(36)}`;

console.log("a locally unique-ish HTML id:");
console.log(generateUniqueId())

// a pseudo-random BigInt
const generateRandomBigInt = () =>
  BigInt(Date.now()) * BigInt(Number.MAX_SAFE_INTEGER) +
  BigInt(Math.floor(Number.MAX_SAFE_INTEGER * Math.random()));

console.log("a pseudo-random BigInt:");
console.log(generateRandomBigInt().toString());

// same but base32-encoded (each char is 5 bits)

console.log("same but base32-encoded (each char is 5 bits):");
console.log(generateRandomBigInt().toString(32));

// extracting the "Date.now" timestamp of when it was generated:

console.log('extracting the "Date.now" timestamp of when it was generated:');
console.log(Number(generateRandomBigInt() / BigInt(Number.MAX_SAFE_INTEGER)))

// generate a run of random BigInt in ascending order

function generateRandomBigIntFactory() {
  let count = 0, prev = 0;
  return () => {
    const now = Date.now();
    if (now === prev) { ++count; }
    else { count = 0; prev = now; }
    return (BigInt(now) * BigInt(16384) + BigInt(count)) * BigInt(Number.MAX_SAFE_INTEGER) +
      BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)); 
  }    
}

// verify the order is ascending
const generate = generateRandomBigIntFactory();
let prev = 0;
for (let i = 0; i < 65536; i++) {
  const num = generate();
  if (num <= prev) console.log(`error: ${prev}, ${num}`);
  prev = num;
}

console.log("the last random BigInt:");
console.log(prev.toString());

Comments

2

use this:for creating unique number in javascript

var uniqueNumber=(new Date().getTime()).toString(36);

It really works. :)

1 Comment

nice and simple.
2

simple solution I found

var today = new Date().valueOf();

console.log( today );

Comments

2

try this

    function generateId() {
    return +new Date();
}

and then assign to variable

const uniqueId = generateId();

Comments

1

This creates an almost guaranteed unique 32 character key client side, if you want just numbers change the "chars" var.

var d = new Date().valueOf();
var n = d.toString();
var result = '';
var length = 32;
var p = 0;
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

for (var i = length; i > 0; --i){
    result += ((i & 1) && n.charAt(p) ? '<b>' + n.charAt(p) + '</b>' : chars[Math.floor(Math.random() * chars.length)]);
    if(i & 1) p++;
};

https://jsfiddle.net/j0evrdf1/1/

Comments

1
    function UniqueValue(d){
        var dat_e = new Date();
        var uniqu_e = ((Math.random() *1000) +"").slice(-4)

        dat_e = dat_e.toISOString().replace(/[^0-9]/g, "").replace(dat_e.getFullYear(),uniqu_e);
        if(d==dat_e)
            dat_e = UniqueValue(dat_e);
        return dat_e;
    }

Call 1: UniqueValue('0')
Call 2: UniqueValue(UniqueValue('0')) // will be complex

Sample Output:
for(var i =0;i<10;i++){ console.log(UniqueValue(UniqueValue('0')));}
60950116113248802
26780116113248803
53920116113248803
35840116113248803
47430116113248803
41680116113248803
42980116113248804
34750116113248804
20950116113248804
03730116113248804

Comments

1

Since milliseconds are not updated every millisecond in node, following is an answer. This generates a unique human readable ticket number. I am new to programming and nodejs. Please correct me if I am wrong.

function get2Digit(value) {
if (value.length == 1) return "0" + "" + value;
else return value;

}

function get3Digit(value) {
if (value.length == 1) return "00" + "" + value;
else return value;

}

function generateID() {
    var d = new Date();
    var year = d.getFullYear();
    var month = get2Digit(d.getMonth() + 1);
    var date = get2Digit(d.getDate());
    var hours = get2Digit(d.getHours());
    var minutes = get2Digit(d.getMinutes());
    var seconds = get2Digit(d.getSeconds());
    var millSeconds = get2Digit(d.getMilliseconds());
    var dateValue = year + "" + month + "" + date;
    var uniqueID = hours + "" + minutes + "" + seconds + "" + millSeconds;

    if (lastUniqueID == "false" || lastUniqueID < uniqueID) lastUniqueID = uniqueID;
    else lastUniqueID = Number(lastUniqueID) + 1;
    return dateValue + "" + lastUniqueID;
}

Comments

1
let uuid = ((new Date().getTime()).toString(36))+'_'+(Date.now() + Math.random().toString()).split('.').join("_")

sample result "k3jobnvt_15750033412250_18299601769317408"

Comments

1

I came across this question while trying to find a simple UID generation technique that was also sortable (so I can order by uid and items will appear in order of creation / uid generation). The major problem with most (all?) of the solutions here is that they either rely on millisecond accuracy (at best) == clashes(!) or a pseudo-random number == clashes(!) && non-sortable(!).

Technique below uses micro-second precision where available (i.e. not where fingerprinting-resistance techniques are in play, e.g. firefox) combined with an incrementing, stateful suffix. Not perfect, or particularly performant for large numbers of IDs (see example with 1,000,000 below), but it works and is reversible.

// return a uid, sortable by creation order
let increment;
let tuidPrev;

const uid = (uidPrev) => {
  // get current time to microsecond precision (if available) and remove decimals
  const tuid = ((performance.timing.navigationStart + performance.now()) * 1000)
    // convert timestamp to base36 string
    .toString(36);

  // previous uid has been provided (stateful)
  if (uidPrev) {
    tuidPrev = uidPrev.slice(0, 10);
    increment = uidPrev.length > 10 ? parseInt(uidPrev.slice(10), 36) : 0;
  }

  // if tuid is changed reset the increment
  if (tuid !== tuidPrev) {
    tuidPrev = tuid;
    increment = 0;
  }

  // return timed uid + suffix (4^36 values) === very unique id!
  return tuid + ('000' + (increment++).toString(36)).slice(-4);
}


// EXAMPLE (check the console!)
const iterations = 1000000;
const uids = [];
const uidMap = {};
const timeMap = {}
const microMap = {};
let time = performance.now();
for (let i = 0; i < iterations; i++) {
  const id = uid();
  uids.push(id);
  uidMap[id] = i;
  timeMap[Date.now()] = i;
  microMap[performance.now()] = i;
}

console.log(`Time taken: ${performance.now() - time}ms`);
console.log('Unique IDs:', Object.keys(uidMap).length.toLocaleString());
console.log('Clashing timestamps:', (iterations - Object.keys(timeMap).length).toLocaleString());
console.log('Clashing microseconds:', (iterations - Object.keys(microMap).length).toLocaleString());
console.log('Sortable:', !uids.slice().sort().find((id, i) => uids[i] !== id))

Comments

1

The usual way in which I generate unique IDs is by using Date.now();

const ID = Date.now();
console.log(ID);

The other way is by using a library as idgp which can be installed using npm.

The link: https://www.npmjs.com/package/idgp

Comments

1

Adding my take on this because I wanted a solution where the UID would be:

  • Likely unique
  • Legible (and can be used in an URL)
  • Sortable (by create date)
const uid = new Date().toISOString().replaceAll(/[-:TZ]/g, '.') + Math.random().toString().substring(2,7)
// '2022.04.15.03.56.36.197.50167'

NOTE: You can tweak the substring second parameter to increase the chances of uniqueness but you will be making the uid longer. Depends on your use case.

Comments

0

Assumed that the solution proposed by @abarber it's a good solution because uses (new Date()).getTime() so it has a windows of milliseconds and sum a tick in case of collisions in this interval, we could consider to use built-in as we can clearly see here in action:

Fist we can see here how there can be collisions in the 1/1000 window frame using (new Date()).getTime():

console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1155:1 1469615396590
VM1155:1 1469615396591
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1156:1 1469615398845
VM1156:1 1469615398846
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1158:1 1469615403045
VM1158:1 1469615403045

Second we try the proposed solution that avoid collisions in the 1/1000 window:

console.log( window.mwUnique.getUniqueID() ); console.log( window.mwUnique.getUniqueID() ); 
VM1159:1 14696154132130
VM1159:1 14696154132131

That said we could consider to use functions like the node process.nextTick that is called in the event loop as a single tick and it's well explained here. Of course in the browser there is no process.nextTick so we have to figure how how to do that. This implementation will install a nextTick function in the browser using the most closer functions to the I/O in the browser that are setTimeout(fnc,0), setImmediate(fnc), window.requestAnimationFrame. As suggested here we could add the window.postMessage, but I leave this to the reader since it needs a addEventListener as well. I have modified the original module versions to keep it simpler here:

getUniqueID = (c => {
 if(typeof(nextTick)=='undefined')
nextTick = (function(window, prefixes, i, p, fnc) {
    while (!fnc && i < prefixes.length) {
        fnc = window[prefixes[i++] + 'equestAnimationFrame'];
    }
    return (fnc && fnc.bind(window)) || window.setImmediate || function(fnc) {window.setTimeout(fnc, 0);};
})(window, 'r webkitR mozR msR oR'.split(' '), 0);
 nextTick(() => {
   return c( (new Date()).getTime() )  
 })
})

So we have in the 1/1000 window:

getUniqueID(function(c) { console.log(c); });getUniqueID(function(c) { console.log(c); });
undefined
VM1160:1 1469615416965
VM1160:1 1469615416966

Comments

0

Maybe even better would be to use getTime() or valueOf(), but this way it returns unique plus human understandable number (representing date and time):

window.getUniqNr = function() {
  var now = new Date(); 
  if (typeof window.uniqCounter === 'undefined') window.uniqCounter = 0; 
  window.uniqCounter++; 
  var m = now.getMonth(); var d = now.getDay(); 
  var h = now.getHours(); var i = now.getMinutes(); 
  var s = now.getSeconds(); var ms = now.getMilliseconds();
  timestamp = now.getFullYear().toString() 
  + (m <= 9 ? '0' : '') + m.toString()
  +( d <= 9 ? '0' : '') + d.toString() 
  + (h <= 9 ? '0' : '') + h.toString() 
  + (i <= 9 ? '0' : '') + i.toString() 
  + (s <= 9 ? '0' : '') + s.toString() 
  + (ms <= 9 ? '00' : (ms <= 99 ? '0' : '')) + ms.toString() 
  + window.uniqCounter; 

  return timestamp;
};
window.getUniqNr();

Comments

0
let now = new Date();
let timestamp = now.getFullYear().toString();
let month = now.getMonth() + 1;
timestamp += (month < 10 ? '0' : '') + month.toString();
timestamp += (now.getDate() < 10 ? '0' : '') + now.getDate().toString();
timestamp += (now.getHours() < 10 ? '0' : '') + now.getHours().toString();
timestamp += (now.getMinutes() < 10 ? '0' : '') + now.getMinutes().toString();
timestamp += (now.getSeconds() < 10 ? '0' : '') + now.getSeconds().toString();
timestamp += (now.getMilliseconds() < 100 ? '0' : '') + now.getMilliseconds().toString();

Comments

0

Easy and always get unique value :

const uniqueValue = (new Date()).getTime() + Math.trunc(365 * Math.random());
**OUTPUT LIKE THIS** : 1556782842762

Comments

0

I have done this way

function uniqeId() {
   var ranDom = Math.floor(new Date().valueOf() * Math.random())
   return _.uniqueId(ranDom);
}

Comments

0
function getUniqueNumber() {

    function shuffle(str) {
        var a = str.split("");
        var n = a.length;
        for(var i = n - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }
        return a.join("");
    }
    var str = new Date().getTime() + (Math.random()*999 +1000).toFixed() //string
    return Number.parseInt(shuffle(str));   
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.