Créez un numéro unique avec l'heure javascript


95

J'ai besoin de générer des numéros d'identification uniques à la volée en utilisant javascript. Dans le passé, j'ai fait cela en créant un nombre en utilisant le temps. Le nombre serait composé de l'année à quatre chiffres, du mois à deux chiffres, du jour à deux chiffres, des heures à deux chiffres, des minutes à deux chiffres, des secondes à deux chiffres et des millisecondes à trois chiffres. Donc, cela ressemblerait à quelque chose comme ceci: 20111104103912732 ... cela donnerait suffisamment de certitude d'un numéro unique pour mes besoins.

Cela fait un moment que je n'ai pas fait ça et je n'ai plus le code. Quelqu'un a-t-il le code pour le faire ou une meilleure suggestion pour générer un identifiant unique?



Avez-vous réfléchi new Date().toISOString ()?
gaspard

Réponses:


66

Si vous voulez juste un numéro unique, alors

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

vous donnerait un chiffre simple. Mais si vous avez besoin de la version lisible, vous êtes dans un peu de traitement:

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()

3
@ Áxel: Je n'ai pas dit que c'était unique, j'ai dit que c'était «unique». bien sûr, l'utilisation d'un horodatage généré côté client va générer des dupes.
Marc B

78
horodatage doit être new Date().getTime();le date.getUTCMilliseconds()retourne un nombre entre 0 et 999. date.getTime()renvoie des millisecondes depuis le 1er janvier 1970. (horodatage normal). w3schools.com/jsref/jsref_obj_date.asp
Automatico

8
-1, car la question portait sur le numéro unique . Le premier bloc de code doit être entièrement omis.
Andrey

Cela peut générer 2 valeurs uniques:function foo1() {console.log(new Date().getUTCMilliseconds()); console.log(new Date().getUTCMilliseconds()); }
Sharikov Vladislav

10
getUTCMillisecondes The value returned by getUTCMilliseconds() is an integer between 0 and 999.. C'est la pire idée pour un identifiant unique, le premier paragraphe doit être supprimé.
gaspard

116

Une meilleure approche serait:

new Date().valueOf();

au lieu de

new Date().getUTCMilliseconds();

valueOf () est "très probablement" un nombre unique. http://www.w3schools.com/jsref/jsref_valueof_date.asp .


19
Ce n'est pas un nombre unique. Les millisecondes ne sont pas suffisamment granulaires pour être considérées comme uniques.
Vamsi Mohan Jayanti

3
Ou simplement+new Date()
thdoan

1
Je viens de lancer une boucle for et j'ai obtenu des résultats en double avec valueOf(). Je viens d'utiliser ceci - +performance.now().toString().replace('.', 7) developer.mozilla.org/en-US/docs/Web/API/Performance/now
Itzik Ben Hutta

1
@ItzikBenHutta a obtenu 3 fois la même valeur. Utilisation d'un processeur multicœur, probablement une condition de concurrence avec les threads.
that-ben

68

Le moyen le plus court de créer un nombre dont vous pouvez être sûr qu'il sera unique parmi autant d'instances distinctes que vous pouvez penser est

Date.now() + Math.random()

S'il y a une différence de 1 milliseconde dans l'appel de fonction, il est garanti à 100% de générer un nombre différent . Pour les appels de fonction dans la même milliseconde, vous ne devriez commencer à vous inquiéter que si vous créez plus de quelques millions de nombres dans cette même milliseconde, ce qui n'est pas très probable.

Pour en savoir plus sur la probabilité d'obtenir un nombre répété dans la même milliseconde, voir https://stackoverflow.com/a/28220928/4617597


7
De plus, si vous souhaitez conserver tous les bits du nombre aléatoire, vous pouvez les générer séparément et les fusionner sous forme de chaînes: new Date (). ValueOf (). ToString (36) + Math.random (). ToString (36) .substr (2) Cela vous donnera une chaîne alphanumérique de 19 caractères qui est une quantité décente d'entropie. Même si la moitié est prévisible.
Erik Pukinskis

2
Cela devrait être la réponse acceptée car en essayant d'autres réponses aux votes plus élevés, j'ai obtenu 2 et même 3 fois la même valeur d'affilée lors d'un appel à partir d'une fonction asynchrone. Cela semble fournir suffisamment de caractère aléatoire pour qu'un processeur standard à 8 cœurs génère 8 chaînes uniques exactement au même moment, assez bien pour mon utilisation.
that-ben

22

Cela peut être réalisé simplement avec le code suivant:

var date = new Date();
var components = [
    date.getYear(),
    date.getMonth(),
    date.getDate(),
    date.getHours(),
    date.getMinutes(),
    date.getSeconds(),
    date.getMilliseconds()
];

var id = components.join("");

6
et si cela est appelé deux fois dans la même milliseconde?
TBE

1
En effet, mais c'était OK pour op: "cela donnerait suffisamment de certitude d'un numéro unique pour mes besoins."
Août Lilleaas

17

Voici ce que je fais quand je veux quelque chose de plus petit qu'un tas de nombres - changer de base.

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

1
@blushrt true, cela peut provoquer de rares conflits. Vous pouvez md5 l'horodatage en utilisant quelque chose comme code.google.com/p/crypto-js , mais pour mes besoins, il était "assez unique" et, plus important encore, plus rapide.
frumbert

@frumbert, ça dépend. MD5 n'est pas non plus résistant aux collisions. Mais dans votre cas, j'ai eu des problèmes très rapidement à cause de toString (36) qui, je suppose, convertit la valeur numérique en sa représentation ascii, pas sûr cependant, mais je peux voir le problème, si vous appelez votre générateur d'uuid assez souvent, seulement 3 derniers les caractères changent, donc les chances que vous soyez en collision sont élevées. Vous obtenez de bien meilleures chances si vous vous en tenez simplement aux nouveaux appels Date.getTime (). Mais bon si cela fonctionnait pour vos besoins, pas de problème, j'en avais besoin pour certains identifiants uniques uniquement pour mon code côté client, j'ai fini par utiliser uuid node lib.
blushrt

J'aime celui la! Je l'ai ajusté (Date.now() + Math.random()).toString(36)pour éviter les conflits en millisecondes. C'est court et génère quelque chose comme "k92g5pux.i36"
Edward le

16

Cela fonctionne plus rapidement que la création d'une Dateinstance, utilise moins de code et produira toujours un numéro unique (localement):

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/

J'ai publié ceci sur Bower et npm: https://github.com/stevenvachon/unique-number

Vous pouvez également utiliser quelque chose de plus élaboré tel que cuid , puid ou shortid pour générer un non-nombre.


1
Il me semble que l'ajout de nombres aléatoires en ferait en fait MOINS une preuve complète. Avec juste l'horodatage, deux nombres devraient être créés exactement à la même milliseconde pour être identiques. En ajoutant deux nombres aléatoires, vous avez maintenant créé de nombreuses combinaisons de nombres, en raison des mathématiques, qui pourraient aboutir au même résultat une fois multipliées. Je sais que c'est peu probable, mais ... n'est-ce pas vrai?
Phil

Hmm, oui. Peut-être qu'une combinaison de ma réponse et de la réponse d'un abarber serait la meilleure.
Steven Vachon

Mis à jour ma réponse. Merci pour la pensée.
Steven Vachon

2
Bon effort, ne pas essayer de choisir votre réponse ... mais cette nouvelle solution ne résout pas réellement le problème "plus d'un identifiant créé à la même milliseconde" car, vous savez ... c'est du javascript, du côté CLIENT. Si un utilisateur différent a créé un nombre à la même milliseconde exacte, il ne serait pas reflété dans uniqueNumber.previous de «l'autre» utilisateur. À moins que vous ne le stockiez quelque part sur le serveur et que vous ne vérifiiez son caractère unique ... il n'y a tout simplement aucun moyen qu'une solution purement basée sur js comme celle-ci puisse être certaine qu'elle crée un numéro unique.
Phil

Eh bien, ce serait un système plus élaboré qu'un simple numéro unique.
Steven Vachon

12

j'utilise

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

Donc, si par hasard le code est déclenché en même temps, il y a aussi une petite chance que les nombres aléatoires soient les mêmes.


Pas sûr que ce new Date()soit utile dur. Vous pourriez obtenir les mêmes numéros avec deux dates différentes
JMaylin

1
Je veux dire, comment est-ce mieux que de simplement faire Math.random()?
JMaylin

7

Cela devrait faire:

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

1
Utile dans de nombreux cas, même si cela ne génère pas vraiment de purs identifiants "uniques", au cas où cette fonction serait appelée plusieurs fois dans la même milliseconde ... Mais de toute façon, pour l'interaction utilisateur et interface utilisateur, c'est bien.
Benjamin Piette

1
cela devrait être la réponse acceptée. Beaucoup de conneries non pertinentes, difficiles et inutiles, et cette réponse donne un temps unique par milliseconde.
gène b.

5

si vous voulez un numéro unique après quelques millisecondes Date.now(), utilisez-le , si vous voulez l'utiliser à l'intérieur d'un, for looppuis utilisez-le Date.now() and Math.random()ensemble

numéro unique dans une boucle for

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

sortie :: tous les nombres sont uniques

15598251485988384 155982514859810330 155982514859860737 155982514859882244 155982514859883316

numéro unique sans Math.random()

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

output :: Les nombres sont répétés

1559825328327 1559825328327 1559825328327 1559825328328 1559825328328


4

Après avoir enquêté en ligne, j'ai trouvé l'objet suivant qui crée un identifiant unique par 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 + '.');
            }
        }            
    }

Cela peut être utile à certaines personnes.

À votre santé

Andrew


c'est la solution la plus simple et la plus fiable à ce jour à propos de cette question. J'ai essayé une solution différente (voir ci-dessous), mais j'ai encore quelques inquiétudes à ce sujet qui nécessitent des développements supplémentaires.
loretoparisi

3

Cela devrait également faire:

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

Implémentation très similaire que vous pouvez trouver dans la fonction lodash UniqueId, pour moi, votre solution est simple et propre.
Kamil Naja

3

Dans 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('')

Exemple:

 > uniqueID()
 > "bxppcnanpuxzpyewttifptbklkurvvetigra"

2

Obtenez toujours un identifiant unique dans JS

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

getUniqueId()    // Call the function

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

//"ka2high4264"

//"ka2hj115905"

//"ka2hj1my690"

//"ka2hj23j287"

//"ka2hj2jp869"

2

En 2020, vous pouvez utiliser l' API Crypto intégrée au navigateur pour générer des valeurs aléatoires cryptographiquement fortes.

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

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

à la fois Uint8Array et Crypto.getRandomValues sont pris en charge sur tous les principaux navigateurs, y compris IE11


1

En publiant cet extrait de code ici pour ma propre référence future (pas garanti mais satisfaisant "unique" assez):

// a valid floating number
window.generateUniqueNumber = function() {
    return new Date().valueOf() + Math.random();
};

// a valid HTML id
window.generateUniqueId = function() {
    return "_" + new Date().valueOf() + Math.random().toFixed(16).substring(2);
};

1

Cela crée un côté client de clé de 32 caractères unique presque garanti, si vous ne voulez que des nombres, changez la variable "chars".

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/


1

utilisez ceci: pour créer un numéro unique en javascript

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

Ça marche vraiment. :)


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;
    }

Appel 1: UniqueValue ('0')
Appel 2: UniqueValue (UniqueValue ('0')) // sera complexe

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


1

Étant donné que les millisecondes ne sont pas mises à jour toutes les millisecondes dans le nœud, voici une réponse. Cela génère un numéro de ticket unique lisible par l'homme. Je suis nouveau dans la programmation et nodejs. S'il vous plait corrigez moi si je me trompe.

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;
}

0

Supposons que la solution proposée par @abarber soit une bonne solution car elle utilise (new Date()).getTime()donc une fenêtre de millisecondes et somme untick en cas de collisions dans cet intervalle, nous pourrions envisager d'utiliser intégré comme nous pouvons clairement le voir ici en action:

Tout d'abord, nous pouvons voir ici comment il peut y avoir des collisions dans le cadre de la fenêtre 1/1000 en utilisant (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

Ensuite, nous essayons la solution proposée qui évite les collisions dans la fenêtre 1/1000:

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

Cela dit, nous pourrions envisager d'utiliser des fonctions comme le nœud process.nextTickappelé dans la boucle d'événements en tant que simple ticket c'est bien expliqué ici . Bien sûr, dans le navigateur, il n'y en a pas process.nextTick, nous devons donc comprendre comment faire cela. Cette mise en œuvre installera une nextTickfonction dans le navigateur en utilisant le plus des fonctions plus proches qui sont le E / S dans le navigateur setTimeout(fnc,0), setImmediate(fnc), window.requestAnimationFrame. Comme suggéré ici, nous pourrions ajouter le window.postMessage, mais je laisse cela au lecteur car il en a également besoin addEventListener. J'ai modifié les versions originales des modules pour les simplifier ici:

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() )  
 })
})

Nous avons donc dans la fenêtre 1/1000:

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

0

Peut-être même mieux serait d'utiliser getTime () ou valueOf (), mais de cette façon, il renvoie un nombre unique et compréhensible par l'homme (représentant la date et l'heure):

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();

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();

0

Facile et obtenez toujours une valeur unique:

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

0

J'ai fait de cette façon

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

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));   
}

0

en référence à la solution #Marcelo Lazaroni ci-dessus

Date.now() + Math.random()

renvoie un nombre tel que celui-ci 1567507511939.4558 (limité à 4 décimales), et donnera des nombres non uniques (ou des collisions) tous les 0,1%.

l'ajout de toString () corrige ce problème

Date.now() + Math.random().toString()

renvoie '15675096840820.04510962122198503' (une chaîne), et est en outre si 'lent' que vous n'obtenez jamais la 'même' milliseconde, de toute façon.


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

exemple de résultat "k3jobnvt_15750033412250_18299601769317408"


0

En utilisant toString(36), légèrement lent, voici la solution la plus rapide et unique:

new Date().getUTCMilliseconds().toString() +
"-" +
Date.now() +
"-" +
filename.replace(/\s+/g, "-").toLowerCase()

0

Pour obtenir un numéro unique:

function getUnique(){
    return new Date().getTime().toString() + window.crypto.getRandomValues(new Uint32Array(1))[0];
}
// or 
function getUniqueNumber(){
    const now = new Date();
    return Number([
        now.getFullYear(),
        now.getMonth(),
        now.getDate(),
        now.getHours(),
        now.getMinutes(),
        now.getUTCMilliseconds(),
        window.crypto.getRandomValues(new Uint8Array(1))[0]
    ].join(""));
}

Exemple:

getUnique()
"15951973277543340653840"

for (let i=0; i<5; i++){
    console.log( getUnique() );
}
15951974746301197061197
15951974746301600673248
15951974746302690320798
15951974746313778184640
1595197474631922766030

getUniqueNumber()
20206201121832230

for (let i=0; i<5; i++){
    console.log( getUniqueNumber() );
}
2020620112149367
2020620112149336
20206201121493240
20206201121493150
20206201121494200

vous pouvez changer la longueur en utilisant:

new Uint8Array(1)[0]
// or
new Uint16Array(1)[0]
// or
new Uint32Array(1)[0]

La question demandait un numéro unique , pas une chaîne aléatoire.
tshimkus le

-1

100% garanti pour générer un nombre différent ...

var Q;
Q = {};
Q.timeInterval;

function genUniqueID(kol) {
	Q.timeInterval = setTimeout(function() {
		document.querySelector('#demo').innerHTML += new Date().valueOf() + '<br>';
		kol--;
		if (kol > 0) {
			genUniqueID(kol);
		}
	}, document.querySelector('#i2').value);
}
<div><input id="i1" type="number" value="5" style="width: 60px;"><label> - Amount</label><br>
    <input id="i2" type="number" value="10" style="width: 60px;"><label> - Millisecond interval</label></div><br>
<div>
    <button onclick="genUniqueID(document.querySelector('#i1').value);">Start</button>
    <button onclick="clearTimeout(Q.timeInterval);">Stop</button>
    <button onclick="document.querySelector('#demo').innerHTML = ''">Clear</button>
</div><br>
<div id="demo"></div>

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.