Buat nomor unik dengan waktu javascript


96

Saya perlu membuat nomor id unik dengan cepat menggunakan javascript. Di masa lalu, saya telah melakukan ini dengan membuat angka menggunakan waktu. Angka tersebut akan terdiri dari empat digit tahun, dua digit bulan, dua digit hari, dua digit jam, dua digit menit, dua digit detik, dan tiga digit milidetik. Jadi akan terlihat seperti ini: 20111104103912732 ... ini akan memberikan kepastian yang cukup tentang nomor unik untuk tujuan saya.

Sudah lama sejak saya melakukan ini dan saya tidak memiliki kode lagi. Ada yang punya kode untuk melakukan ini, atau punya saran yang lebih baik untuk menghasilkan ID unik?



Sudahkah Anda mempertimbangkan new Date().toISOString ()?
terengah

Jawaban:


67

Jika Anda hanya ingin nomor unik, maka

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

akan memberi Anda nomor sederhana. Tetapi jika Anda membutuhkan versi yang dapat dibaca, Anda sedang dalam proses:

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: Saya tidak mengatakan itu unik, saya mengatakan itu "unik-ish". tentu saja menggunakan timestamp yang dihasilkan sisi klien akan menghasilkan penipuan.
Marc B

79
timestamp harus new Date().getTime();yang date.getUTCMilliseconds()kembali angka antara 0 dan 999. date.getTime()kembali milidetik sejak 1 Jan 1970. (timestamp normal). w3schools.com/jsref/jsref_obj_date.asp
Automatico

8
-1, karena pertanyaannya tentang nomor unik . Blok kode pertama harus dihilangkan seluruhnya.
Andrey

Ini dapat menghasilkan 2 nilai unik: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.. Ini adalah ide terburuk untuk id unik, paragraf pertama harus dihapus.
terengah

118

Pendekatan yang lebih baik adalah:

new Date().valueOf();

dari pada

new Date().getUTCMilliseconds();

valueOf () "kemungkinan besar" adalah nomor unik. http://www.w3schools.com/jsref/jsref_valueof_date.asp .


19
Ini bukan angka unik .. milidetik tidak cukup terperinci untuk dianggap unik.
Vamsi Mohan Jayanti

3
Atau sederhananya+new Date()
lakukan

1
Saya baru saja menjalankan loop for dan mendapatkan hasil duplikat dengan valueOf(). Saya hanya menggunakan ini - +performance.now().toString().replace('.', 7) developer.mozilla.org/en-US/docs/Web/API/Performance/now
Itzik Ben Hutta

1
@ItzikBenHutta Mendapat nilai yang sama 3 kali lipat. Menggunakan CPU multi-core, mungkin kondisi balapan dengan utas.
that-ben

70

Cara terpendek untuk membuat nomor yang Anda yakin akan unik di antara banyak contoh terpisah yang dapat Anda pikirkan adalah

Date.now() + Math.random()

Jika ada perbedaan 1 milidetik dalam pemanggilan fungsi, dijamin 100% akan menghasilkan nomor yang berbeda . Untuk pemanggilan fungsi dalam milidetik yang sama, Anda seharusnya hanya mulai khawatir jika Anda membuat lebih dari beberapa juta nomor dalam milidetik yang sama, yang sangat tidak mungkin.

Untuk informasi lebih lanjut tentang kemungkinan mendapatkan nomor berulang dalam milidetik yang sama lihat https://stackoverflow.com/a/28220928/4617597


7
Juga, jika Anda ingin menyimpan semua bit dari bilangan acak, Anda dapat membuatnya secara terpisah dan menggabungkannya sebagai string: new Date (). ValueOf (). ToString (36) + Math.random (). ToString (36) .substr (2) Itu akan memberi Anda 19 karakter string alfanumerik yang merupakan jumlah entropi yang layak. Meskipun setengahnya bisa diprediksi.
Erik Pukinskis

2
Ini harus menjadi jawaban yang diterima seperti ketika mencoba jawaban lain yang dipilih lebih tinggi, saya mendapat 2 dan bahkan 3 kali nilai yang sama berturut-turut saat memanggil dari fungsi async. Ini tampaknya memberikan keacakan yang cukup untuk CPU 8-core standar untuk menghasilkan 8 string unik tepat pada saat yang sama, cukup baik untuk saya gunakan.
that-ben

22

Ini dapat dicapai hanya dengan kode berikut:

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
bagaimana jika ini dipanggil dua kali dalam milidetik yang sama?
TBE

1
Memang, tapi tidak apa-apa untuk op: "ini akan memberikan kepastian yang cukup tentang nomor unik untuk tujuan saya."
Agustus Lilleaas

17

Inilah yang saya lakukan ketika saya menginginkan sesuatu yang lebih kecil dari sekumpulan angka - ubah basis.

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

1
@ Blushrt benar, ini dapat menyebabkan bentrokan yang jarang terjadi. Anda dapat membuat stempel waktu menggunakan sesuatu seperti code.google.com/p/crypto-js , tetapi untuk tujuan saya itu "cukup unik", dan yang lebih penting, lebih cepat.
frumbert

@frumbert, itu tergantung. MD5 juga tidak tahan benturan. Tetapi dalam kasus Anda, saya mendapat masalah dengan sangat cepat karena toString (36) yang saya asumsikan mengubah nilai numerik menjadi representasi ascii itu, meskipun tidak yakin, tetapi saya dapat melihat masalahnya, jika Anda memanggil generator uuid Anda cukup sering, hanya 3 yang terakhir karakter berubah sehingga kemungkinan besar Anda akan mengalami tabrakan. Anda mendapatkan peluang yang jauh lebih baik jika Anda tetap menggunakan panggilan Date.getTime () baru. Tapi hei jika itu berhasil untuk tujuan Anda, tidak masalah, saya membutuhkannya untuk beberapa id unik hanya untuk kode sisi klien saya, akhirnya menggunakan uuid node lib.
blushrt

Saya suka yang ini! Saya telah menyesuaikannya (Date.now() + Math.random()).toString(36)untuk mencegah bentrokan milidetik. Ini pendek dan menghasilkan sesuatu seperti "k92g5pux.i36"
Edward

16

Ini bekerja lebih cepat daripada membuat Dateinstance, menggunakan lebih sedikit kode dan akan selalu menghasilkan nomor unik (secara lokal):

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/

Saya telah merilis ini di Bower dan npm: https://github.com/stevenvachon/unique-number

Anda juga bisa menggunakan sesuatu yang lebih rumit seperti cuid , puid atau shortid untuk menghasilkan non-number.


1
Menurut saya, menambahkan nomor acak sebenarnya akan membuatnya KURANG bukti penuh. Hanya dengan stempel waktu, dua angka harus dibuat pada milidetik yang sama persis agar sama. Dengan menambahkan dua angka acak, Anda sekarang telah membuat banyak kombinasi angka, karena matematika, yang bisa berakhir dengan hasil yang sama saat dikalikan. Aku tahu itu tidak mungkin, tapi ... bukankah itu benar?
Phil

Hmm ya. Mungkin kombinasi dari jawaban saya dan jawaban penulis adalah yang terbaik.
Steven Vachon

Memperbarui jawaban saya. Terima kasih untuk pemikirannya.
Steven Vachon

2
Usaha yang bagus, tidak mencoba memilih jawaban Anda ... tetapi solusi baru ini tidak benar-benar menyelesaikan masalah "lebih dari satu id dibuat pada milidetik yang sama" karena, ya tahu .. itu javascript, di sisi KLIEN. Jika pengguna yang berbeda membuat angka pada milidetik yang sama persis, itu tidak akan tercermin dalam uniqueNumber.previous dari pengguna 'other'. Kecuali jika Anda menyimpannya di server di suatu tempat dan memeriksa keunikannya ... tidak mungkin solusi murni berbasis js seperti ini dapat memastikan bahwa ia membuat nomor unik.
Phil

Nah, itu akan menjadi sistem yang lebih rumit dari sekedar nomor unik.
Steven Vachon

12

saya menggunakan

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

Jadi, jika kebetulan kode tersebut diaktifkan pada saat yang sama, ada kemungkinan kecil bahwa nomor acaknya akan sama.


Tidak yakin new Date()tangguh berguna. Anda bisa mendapatkan nomor yang sama dengan dua tanggal berbeda
JMaylin

1
Maksud saya, bagaimana itu lebih baik daripada sekadar melakukan Math.random()?
JMaylin

7

Ini harus dilakukan:

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

1
Berguna untuk banyak kasus, meskipun ini tidak benar-benar menghasilkan id "unik" murni, jika fungsi ini dipanggil beberapa kali dalam milidetik yang sama ... Tapi bagaimanapun, untuk interaksi pengguna dan UI, itu bagus.
Benjamin Piette

1
ini harus menjadi jawaban yang diterima. Banyak omong kosong tidak relevan yang sulit dan tidak perlu, dan jawaban ini memberikan waktu unik per milidetik.
gen b.

5

Jika Anda menginginkan nomor unik setelah beberapa mili detik maka gunakan Date.now(), jika Anda ingin menggunakannya di dalam a for loopmaka gunakan Date.now() and Math.random()bersama

nomor unik di dalam for loop

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

keluaran :: semua nomor unik

15598251485988384 155982514859810330 155982514859860737 155982514859882244 155982514859883316

nomor unik tanpa Math.random()

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

output :: Angka diulang

1559825328327 1559825328327 1559825328327 1559825328328 1559825328328


4

Dari penyelidikan online saya menemukan objek berikut yang membuat id unik per sesi:

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

Ini mungkin membantu bagi sebagian orang.

Bersulang

Andrew


ini adalah solusi paling sederhana dan bukti kesalahan hingga saat ini tentang pertanyaan ini. Saya telah mencoba solusi lain (lihat di bawah), tetapi saya masih memiliki beberapa kekhawatiran tentang hal itu yang memerlukan pengembangan lebih lanjut.
loretoparisi

3

Ini juga harus dilakukan:

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

Implementasi yang sangat mirip dapat Anda temukan di fungsi Lodash UniqueId, bagi saya, solusi Anda sederhana dan bersih.
Kamil Naja

3

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

Contoh:

 > uniqueID()
 > "bxppcnanpuxzpyewttifptbklkurvvetigra"

2

Selalu dapatkan ID unik di JS

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

getUniqueId()    // Call the function

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

//"ka2high4264"

//"ka2hj115905"

//"ka2hj1my690"

//"ka2hj23j287"

//"ka2hj2jp869"

2

Pada tahun 2020, Anda dapat menggunakan Crypto API dalam browser untuk menghasilkan nilai acak yang kuat secara kriptografis.

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

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

baik Uint8Array dan Crypto.getRandomValues didukung di semua browser utama, termasuk IE11


1

Memposting potongan kode ini di sini untuk referensi saya di masa mendatang (tidak dijamin, tetapi cukup "unik" yang memuaskan):

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

Ini menciptakan sisi klien kunci unik 32 karakter yang hampir dijamin, jika Anda hanya ingin angka mengubah 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

gunakan ini: untuk membuat nomor unik di javascript

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

Ini benar-benar berhasil. :)


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

Panggilan 1: UniqueValue ('0')
Call 2: UniqueValue (UniqueValue ('0')) // akan menjadi kompleks

Contoh Keluaran:
for (var i = 0; i <10; i ++) {console.log (UniqueValue (UniqueValue ('0')));}
60950116113248802
26780116113248803
53920116113248803
35840116113248803
47430116113248803
41680116113248803
53920116113248803
35840116113248803
47430116113248803
41680116113248803


1

Karena milidetik tidak diperbarui setiap milidetik dalam node, berikut adalah jawabannya. Ini menghasilkan nomor tiket unik yang dapat dibaca manusia. Saya baru mengenal pemrograman dan nodejs. Tolong koreksi saya jika saya salah.

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

Diasumsikan bahwa solusi yang diusulkan oleh @abarber itu adalah solusi yang baik karena menggunakan (new Date()).getTime()sehingga memiliki jendela milidetik dan jumlah atick jika terjadi tabrakan dalam interval ini, kami dapat mempertimbangkan untuk menggunakan bawaan seperti yang dapat kita lihat dengan jelas di sini beraksi:

Pertama, kita dapat melihat di sini bagaimana bisa terjadi tabrakan di bingkai jendela 1/1000 menggunakan (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

Kedua, kami mencoba solusi yang diusulkan yang menghindari tabrakan di jendela 1/1000:

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

Yang mengatakan kita dapat mempertimbangkan untuk menggunakan fungsi seperti node process.nextTickyang dipanggil dalam event loop sebagai satu tickdan dijelaskan dengan baik di sini . Tentu saja di browser tidak ada process.nextTickjadi kita harus memikirkan bagaimana cara melakukannya. Ini implementasi akan menginstal nextTickfungsi dalam browser menggunakan sebagian besar fungsi lebih dekat dengan I / O di browser yang setTimeout(fnc,0), setImmediate(fnc), window.requestAnimationFrame. Seperti yang disarankan di sini kita bisa menambahkan window.postMessage, tapi saya serahkan ini kepada pembaca karena perlu addEventListenerjuga. Saya telah memodifikasi versi modul asli agar lebih sederhana di sini:

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

Jadi kita ada di jendela 1/1000:

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

0

Mungkin lebih baik lagi menggunakan getTime () atau valueOf (), tetapi cara ini mengembalikan angka unik plus yang dapat dimengerti manusia (mewakili tanggal dan waktu):

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

Mudah dan selalu dapatkan nilai unik:

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

0

Saya telah melakukan cara ini

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

mengacu pada solusi #Marcelo Lazaroni di atas

Date.now() + Math.random()

mengembalikan angka seperti ini 1567507511939.4558 (terbatas pada 4 desimal), dan akan memberikan angka tidak unik (atau benturan) setiap 0,1%.

menambahkan toString () memperbaiki ini

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

mengembalikan '15675096840820.04510962122198503' (string), dan lebih jauh lagi 'lambat' sehingga Anda tidak akan pernah mendapatkan milidetik yang 'sama'.


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

hasil sampel "k3jobnvt_15750033412250_18299601769317408"


0

Menggunakan toString(36), sedikit lambat, berikut adalah solusi yang lebih cepat dan unik:

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

0

Untuk mendapatkan nomor unik:

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

Contoh:

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

Anda dapat mengubah panjangnya menggunakan:

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

Pertanyaan meminta nomor unik , bukan string acak.
tshimkus

0

solusi sederhana yang saya temukan

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

console.log (hari ini);

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.