Crea un numero univoco con l'ora javascript


95

Ho bisogno di generare numeri di identificazione univoci al volo utilizzando javascript. In passato, l'ho fatto creando un numero usando il tempo. Il numero sarebbe composto da anno a quattro cifre, mese a due cifre, giorno a due cifre, ora a due cifre, minuti a due cifre, secondi a due cifre e millisecondi a tre cifre. Quindi sarebbe simile a questo: 20111104103912732 ... questo darebbe abbastanza certezza di un numero univoco per i miei scopi.

È passato un po 'di tempo da quando l'ho fatto e non ho più il codice. Qualcuno ha il codice per farlo o ha un suggerimento migliore per generare un ID univoco?



Hai considerato new Date().toISOString ()?
gaspard

Risposte:


66

Se vuoi solo un numero univoco, allora

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

ti darebbe un numero semplice. Ma se hai bisogno della versione leggibile, sei pronto per un po 'di elaborazione:

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: non ho detto che è unico, ho detto che è "unico". ovviamente l'utilizzo di un timestamp generato dal lato client genererà doppioni.
Marc B

78
timestamp deve essere new Date().getTime();il valore date.getUTCMilliseconds()restituito da un numero compreso tra 0 e 999. date.getTime()restituisce millisecondi dal 1 ° gennaio 1970. (timestamp normale). w3schools.com/jsref/jsref_obj_date.asp
Automatico

8
-1, poiché la domanda riguardava il numero univoco . Il primo blocco di codice dovrebbe essere completamente omesso.
Andrey

Questo può generare 2 valori univoci:function foo1() {console.log(new Date().getUTCMilliseconds()); console.log(new Date().getUTCMilliseconds()); }
Sharikov Vladislav

10
getUTCMilliseconds The value returned by getUTCMilliseconds() is an integer between 0 and 999.. Questa è l'idea peggiore per ID univoco, il primo paragrafo dovrebbe essere rimosso.
gaspard

116

Un approccio migliore sarebbe:

new Date().valueOf();

invece di

new Date().getUTCMilliseconds();

valueOf () è "molto probabilmente" un numero univoco. http://www.w3schools.com/jsref/jsref_valueof_date.asp .


19
Non è un numero univoco .. i millisecondi non sono sufficientemente granulari per essere considerati unici.
Vamsi Mohan Jayanti

3
O semplicemente+new Date()
thdoan

1
Ho appena eseguito un ciclo for e ho ottenuto risultati duplicati con valueOf(). Lo uso solo - +performance.now().toString().replace('.', 7) developer.mozilla.org/en-US/docs/Web/API/Performance/now
Itzik Ben Hutta

1
@ItzikBenHutta ha ottenuto 3 volte lo stesso valore. Utilizzando CPU multi-core, probabilmente una condizione di competizione con i thread.
quel-ben

68

Il modo più breve per creare un numero che puoi essere abbastanza sicuro sarà unico tra tutte le istanze separate che puoi pensare è

Date.now() + Math.random()

Se c'è una differenza di 1 millisecondo nella chiamata di funzione, è garantito al 100% che generi un numero diverso . Per le chiamate di funzione entro lo stesso millisecondo dovresti iniziare a preoccuparti solo se stai creando più di qualche milione di numeri entro questo stesso millisecondo, il che non è molto probabile.

Per ulteriori informazioni sulla probabilità di ottenere un numero ripetuto entro lo stesso millisecondo, vedere https://stackoverflow.com/a/28220928/4617597


7
Inoltre, se vuoi mantenere tutti i bit del numero casuale, puoi generarli separatamente e unirli come stringhe: new Date (). ValueOf (). ToString (36) + Math.random (). ToString (36) .substr (2) Questo ti darà una stringa alfanumerica di 19 caratteri che è una discreta quantità di entropia. Anche se la metà è prevedibile.
Erik Pukinskis

2
Questa dovrebbe essere la risposta accettata poiché quando provo altre risposte con voti più alti, ho ottenuto 2 e anche 3 volte lo stesso valore di fila quando chiamo da una funzione asincrona. Questo sembra fornire abbastanza casualità per una CPU standard a 8 core per generare 8 stringhe uniche esattamente nello stesso momento, abbastanza buono per il mio uso.
quel-ben

22

Ciò può essere ottenuto semplicemente con il seguente codice:

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
cosa succede se viene chiamato due volte nello stesso millisecondo?
TBE

1
Effettivamente, ma per op: "questo darebbe abbastanza certezza di un numero univoco per i miei scopi".
August Lillea come

17

Ecco cosa faccio quando voglio qualcosa di più piccolo di un mucchio di numeri: cambia base.

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

1
@blushrt true, può causare rari scontri. Potresti modificare il timestamp utilizzando qualcosa come code.google.com/p/crypto-js , ma per i miei scopi era "abbastanza unico" e, cosa più importante, più veloce.
frumbert

@frumbert, dipende. Anche MD5 non è resistente alle collisioni. Ma nel tuo caso mi sono messo nei guai molto velocemente a causa di toString (36) che presumo converta il valore numerico nella sua rappresentazione ascii, non sono sicuro, ma posso vedere il problema, se chiami il tuo generatore di uuid abbastanza spesso, durano solo 3 i caratteri stanno cambiando, quindi è molto probabile che si verifichi una collisione. Ottieni probabilità molto migliori se ti limiti alle nuove chiamate Date.getTime (). Ma hey se ha funzionato per i tuoi scopi, nessun problema, ne avevo bisogno per alcuni ID univoci solo per il mio codice lato client, ho finito per usare il nodo uuid lib.
arrossire

Io amo questo! L'ho regolato (Date.now() + Math.random()).toString(36)per evitare scontri di millisecondi. È breve e genera qualcosa come "k92g5pux.i36"
Edward

16

Funziona più velocemente della creazione di Dateun'istanza, utilizza meno codice e produrrà sempre un numero univoco (localmente):

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/

L'ho pubblicato su Bower e npm: https://github.com/stevenvachon/unique-number

Puoi anche usare qualcosa di più elaborato come cuid , puid o shortid per generare un non numero.


1
Mi sembra che l'aggiunta di numeri casuali renderebbe effettivamente MENO una prova completa. Con solo il timestamp, due numeri dovrebbero essere creati esattamente nello stesso millisecondo per essere lo stesso. Aggiungendo due numeri casuali, ora hai creato molte combinazioni di numeri, a causa della matematica, che potrebbero finire con lo stesso risultato quando moltiplicate. So che è improbabile, ma ... non è vero?
Phil

Hmm, sì. Forse una combinazione della mia risposta e della risposta di abarber sarebbe la migliore.
Steven Vachon

Ho aggiornato la mia risposta. Grazie del pensiero.
Steven Vachon

2
Buon sforzo, non cercare di scegliere la tua risposta ... ma questa nuova soluzione in realtà non risolve il problema "più di un ID creato nello stesso millisecondo" perché, sai .. è javascript, dal lato CLIENTE. Se un altro utente ha creato un numero nello stesso esatto millisecondo, non si rifletterebbe in uniqueNumber.previous dell '"altro" utente. A meno che non lo memorizzi sul server da qualche parte e controlli l'unicità ... non c'è modo che una soluzione puramente basata su js come questa possa essere certo che stia creando un numero univoco.
Phil

Bene, sarebbe un sistema più elaborato di un semplice numero univoco.
Steven Vachon

12

Io uso

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

Quindi, se per caso il codice viene attivato nello stesso momento, c'è anche una piccola possibilità che i numeri casuali siano gli stessi.


Non sono sicuro che new Date()sia utile duro. Potresti ottenere gli stessi numeri con due date diverse
JMaylin

1
Voglio dire, come è meglio che semplicemente fare Math.random()?
JMaylin

7

Questo dovrebbe fare:

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

1
Utile per molti casi, anche se questo non genera veri e propri id "unici" puri, nel caso in cui questa funzione venga chiamata più volte nello stesso millisecondo ... Ma comunque, per l'interazione tra utente e interfaccia utente, va bene.
Benjamin Piette

1
questa dovrebbe essere la risposta accettata. Un sacco di schifezze irrilevanti che sono difficili e non necessarie, e questa risposta fornisce un tempo unico per ogni millisecondo.
gene b.

5

se vuoi un numero univoco dopo pochi mili secondi, usalo Date.now(), se vuoi usarlo all'interno di un for loopallora usalo Date.now() and Math.random()insieme

numero univoco all'interno di un ciclo for

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

output :: tutti i numeri sono unici

15598251485988384 155982514859810330 155982514859860737 155982514859882244 155982514859883316

numero univoco senza Math.random()

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

output :: I numeri vengono ripetuti

1559825328327 1559825328327 1559825328327 1559825328328 1559825328328


4

Dall'indagine online ho trovato il seguente oggetto che crea un ID univoco per sessione:

        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 + '.');
            }
        }            
    }

Forse è utile per alcune persone.

Saluti

Andrea


questa è la soluzione più semplice ea prova di errore fino ad oggi su questa domanda. Ho provato una soluzione diversa (vedi sotto), ma ho ancora alcune preoccupazioni al riguardo che necessitano di ulteriore sviluppo.
loretoparisi

3

Anche questo dovrebbe fare:

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

Implementazione molto simile che puoi trovare nella funzione UniqueId di lodash, per me la tua soluzione è semplice e pulita.
Kamil Naja

3

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

Esempio:

 > uniqueID()
 > "bxppcnanpuxzpyewttifptbklkurvvetigra"

2

Ottieni sempre un ID univoco in JS

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

getUniqueId()    // Call the function

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

//"ka2high4264"

//"ka2hj115905"

//"ka2hj1my690"

//"ka2hj23j287"

//"ka2hj2jp869"

2

Nel 2020, puoi utilizzare l' API Crypto nel browser per generare valori casuali crittograficamente forti.

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

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

sia Uint8Array che Crypto.getRandomValues sono supportati su tutti i principali browser, incluso IE11


1

Pubblicazione di questo frammento di codice qui per mio riferimento futuro (non garantito ma sufficientemente "unico" soddisfacente):

// 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

Questo crea una chiave lato client univoca quasi garantita di 32 caratteri, se vuoi solo numeri cambia la var "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

usa questo: per creare un numero univoco in javascript

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

Funziona veramente. :)


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

Chiamata 1: UniqueValue ('0')
Chiamata 2: UniqueValue (UniqueValue ('0')) // sarà complessa

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


1

Poiché i millisecondi non vengono aggiornati ogni millisecondo nel nodo, la risposta è la seguente. Questo genera un numero di ticket univoco leggibile dall'uomo. Sono nuovo nella programmazione e in nodejs. Perfavore, correggimi se sbaglio.

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

Supponendo che la soluzione proposta da @abarber sia una buona soluzione perché usa (new Date()).getTime()quindi ha una finestra di millisecondi e somma a tickin caso di collisioni in questo intervallo, potremmo considerare di utilizzare built-in come possiamo vedere chiaramente qui in azione:

Per prima cosa possiamo vedere qui come ci possono essere collisioni nel telaio della finestra 1/1000 utilizzando (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

In secondo luogo proviamo la soluzione proposta che evita le collisioni nella finestra 1/1000:

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

Detto questo, potremmo considerare di utilizzare funzioni come il nodo process.nextTickche viene chiamato nel ciclo di eventi come un singolo ticked è ben spiegato qui . Ovviamente nel browser non c'è, process.nextTickquindi dobbiamo capire come farlo. Questa implementazione installerà una nextTickfunzione nel browser utilizzando le maggior parte delle funzioni più vicino alla I / O nel browser che sono setTimeout(fnc,0), setImmediate(fnc),window.requestAnimationFrame . Come suggerito qui potremmo aggiungere il window.postMessage, ma lascio questo al lettore poiché ha bisogno di unaddEventListener . Ho modificato le versioni del modulo originale per renderlo più semplice qui:

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

Quindi abbiamo nella finestra 1/1000:

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

0

Forse sarebbe ancora meglio usare getTime () o valueOf (), ma in questo modo restituisce un numero univoco più comprensibile dall'uomo (che rappresenta la data e l'ora):

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 e ottieni sempre un valore unico:

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

0

Ho fatto in questo modo

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

in riferimento alla soluzione #Marcelo Lazaroni sopra

Date.now() + Math.random()

restituisce un numero come questo 1567507511939.4558 (limitato a 4 decimali) e fornirà numeri non univoci (o collisioni) ogni 0,1%.

l'aggiunta di toString () risolve questo problema

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

restituisce "15675096840820.04510962122198503" (una stringa) ed è ulteriormente così "lento" da non ottenere mai lo "stesso" millisecondo, comunque.


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

risultato di esempio "k3jobnvt_15750033412250_18299601769317408"


0

Utilizzando toString(36), leggermente lento, ecco la soluzione più veloce e unica:

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

0

Per ottenere un numero univoco:

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

Esempio:

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

puoi modificare la lunghezza utilizzando:

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

La domanda richiedeva un numero univoco , non una stringa casuale.
tshimkus

-1

100% garantito per generare un numero diverso ...

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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.