JavaScript時間で一意の番号を作成する


95

JavaScriptを使用してオンザフライで一意のID番号を生成する必要があります。以前は、時間を使用して数値を作成することでこれを実現しました。数字は、4桁の年、2桁の月、2桁の日、2桁の時間、2桁の分、2桁の秒、および3桁のミリ秒で構成されます。したがって、次のようになります。

私がこれを実行してからしばらく経ちましたが、コードはもうありません。誰かがこれを行うためのコードを持っているか、一意のIDを生成するためのより良い提案がありますか?



検討しましたnew Date().toISOString ()か?
Gaspard

回答:


66

ユニークな数字だけが必要な場合は、

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

単純な番号を取得します。ただし、読み取り可能なバージョンが必要な場合は、少し処理を行います。

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:ユニークだとは言いませんでしたが、「ユニークっぽい」と言いました。もちろん、タイムスタンプで生成されたクライアント側を使用すると、複製が生成されます。
Marc B

78
タイムスタンプはあるべきで0と999の間の戻り数1月1日1970年(通常タイムスタンプ)以降の戻りミリ秒。w3schools.com/jsref/jsref_obj_date.aspnew Date().getTime();date.getUTCMilliseconds()date.getTime()
Automatico

8
質問は一意の数に関するものだったため、-1 。コードの最初のブロックは完全に省略する必要があります。
Andrey

:これは2つの一意の値を生成することができますfunction foo1() {console.log(new Date().getUTCMilliseconds()); console.log(new Date().getUTCMilliseconds()); }
Sharikovウラジスラフ

10
getUTCMilliseconds The value returned by getUTCMilliseconds() is an integer between 0 and 999.。これは一意のIDの最悪のアイデアです。最初の段落を削除する必要があります。
Gaspard 2016年

116

より良いアプローチは:

new Date().valueOf();

の代わりに

new Date().getUTCMilliseconds();

valueOf()は一意である可能性が最も高いです。 http://www.w3schools.com/jsref/jsref_valueof_date.asp


19
一意の数値ではありません。ミリ秒は、一意であると見なされるほど細かくありません。
Vamsi Mohan Jayanti 2014年

3
あるいは単に+new Date()
thdoan

1
forループを実行しただけで、で重複した結果が得られましたvalueOf()。-私はこの使用+performance.now().toString().replace('.', 7) developer.mozilla.org/en-US/docs/Web/API/Performance/now
ItzikベンHutta

1
@ItzikBenHutta同じ値を3回取得しました。マルチコアCPUを使用している、おそらくスレッドとの競合状態。
that-ben

68

確かな数を作成する最も簡単な方法は、考えられる限り多くの個別のインスタンス間で一意になることです。

Date.now() + Math.random()

関数呼び出しに1ミリ秒の差がある場合、別の数値が生成されることが100%保証されます。同じミリ秒内の関数呼び出しの場合、この同じミリ秒内に数百万を超える数を作成している場合にのみ心配する必要があります。

同じミリ秒内に繰り返し数を取得する確率の詳細については、https: //stackoverflow.com/a/28220928/4617597を参照してください


7
また、乱数のすべてのビットを保持したい場合は、それらを個別に生成して文字列としてマージできます:new Date()。valueOf()。toString(36)+ Math.random()。toString(36).substr (2)これにより、19文字の英数字の文字列が適切な量のエントロピーになります。その半分は予測可能ですが。
エリックプキンスキス2017

2
他の投票数の多い回答を試すとき、これは受け入れられた回答であるはずです。非同期関数から呼び出すと、同じ値が2倍、さらには3倍連続して表示されます。これは、標準の8コアCPUが同時に8つの一意の文字列を生成するのに十分なランダム性を提供するようで、私の使用には十分です。
that-ben

22

これは、次のコードで簡単に実現できます。

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
これが同じミリ秒に2回呼び出された場合はどうなりますか?
TBE、2016年

1
確かに、しかしそれはopにとってはOKでした:「これは私の目的のために一意の番号の十分な確実性を与えるでしょう」。
August Lilleaas 2016年

17

数字の束よりも小さいものが欲しいときに変更します-変更ベース。

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

1
@blushrt true、まれな衝突を引き起こす可能性があります。code.google.com/p/crypto-jsのようなものを使用してタイムスタンプをmd5することができますが、私の目的では「十分にユニーク」であり、さらに重要なことに、より高速でした。
フランベルト

@frumbert、場合によります。MD5も衝突耐性はありません。しかし、あなたの場合、数値をASCII表現に変換すると想定しているtoString(36)のため、私は非常に速く問題に遭遇しましたが、確かではありませんが、uuidジェネレータを頻繁に呼び出すと、最後の3つしか問題が表示されません文字が変化しているため、衝突が発生する可能性が高くなっています。新しいDate.getTime()呼び出しを続けるだけで、はるかに良いオッズが得られます。しかし、それがあなたの目的のために機能した場合は問題ありません。問題はありません。クライアント側のコードだけにいくつかの一意のIDが必要だったため、結局、uuidノードlibを使用していました。
blushrt 2015年

これ大好き!(Date.now() + Math.random()).toString(36)ミリ秒の衝突を防ぐために調整しました。短く、「k92g5pux.i36」のようなものを生成します
エドワード

16

これは、Dateインスタンスを作成するよりも速く実行され、使用するコードが少なく、常に一意の番号が(ローカルで)生成されます。

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/

これをBowerおよびnpmでリリースしました:https : //github.com/stevenvachon/unique-number

また、のようなより複雑なものを使用することができCUIDPUIDまたはshortid非数を生成します。


1
乱数を追加すると、実際には完全な証明が少なくなるように思えます。タイムスタンプだけで、2つの数値を同じミリ秒で作成して同じにする必要があります。2つの乱数を追加することにより、数学により、乗算すると同じ結果になる可能性のある数値の多くの組み合わせを作成しました。ありそうもないことはわかっていますが、そうではありませんか?
Phil

うーん、はい。おそらく、私の答えと理髪店の答えを組み合わせるのが最善でしょう。
Steven Vachon

私の答えを更新しました。考えてくれてありがとう。
Steven Vachon、2015年

2
良い努力、あなたの答えを選ぶのではなく...しかし、この新しい解決策は実際には「同じミリ秒で作成された複数のID」の問題を解決しません。別のユーザーが同じ正確なミリ秒で数値を作成した場合、その数値は「他の」ユーザーのuniqueNumber.previousに反映されません。あなたは、サーバーのどこかに保管して一意性をチェックしない限り...このような純粋なJSベースのソリューションができることだけで方法はありません特定のそれは固有の番号を作成しています。
Phil

まあ、それは単なる一意の番号よりも複雑なシステムになります。
Steven Vachon、2015年

12

私が使う

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

そのため、万が一、コードが同時に実行された場合、乱数が同じになる可能性はわずかです。


確かにnew Date()タフな使い道はありません。2つの異なる日付で同じ数値を取得することができます
JMaylin

1
つまり、単に行うよりもどのように優れているのMath.random()ですか?
JMaylin 2016年

7

これは行う必要があります:

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

1
多くの場合に便利ですが、この関数が同じミリ秒内に複数回呼び出された場合、これが実際に純粋な「一意の」IDを生成することはありません。
ベンジャミンピエット2015

1
これは受け入れられる答えになるはずです。困難で不必要な無関係のがらくたがたくさんあり、この答えはミリ秒ごとにユニークな時間を与えます。
遺伝子b。

5

数ミリ秒後に一意の番号が必要なDate.now()場合はを使用し、内部でfor loop使用する場合はDate.now() and Math.random()一緒に使用します

forループ内の一意の番号

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

出力::すべての数値は一意です

15598251485988384 155982514859810330 155982514859860737 155982514859882244 155982514859883316

なしの一意の番号 Math.random()

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

出力::数字が繰り返されます

1559825328327 1559825328327 1559825328327 1559825328328 1559825328328


4

オンラインで調査したところ、セッションごとに一意のIDを作成する次のオブジェクトが思い付きました。

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

一部の人に役立つかもしれません。

乾杯

アンドリュー


これは、この質問についてこれまでで最も簡単でエラーのないソリューションです。別の解決策を試してみましたが(下記を参照)、さらに開発が必要であるという懸念がまだあります。
loretoparisi

3

これも行う必要があります:

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

lodash UniqueId関数で見つけることができる非常に類似した実装、私にとって、あなたのソリューションはシンプルでクリーンです。
Kamil Naja

3

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

例:

 > uniqueID()
 > "bxppcnanpuxzpyewttifptbklkurvvetigra"

2

JSで常に一意のIDを取得する

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

getUniqueId()    // Call the function

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

//"ka2high4264"

//"ka2hj115905"

//"ka2hj1my690"

//"ka2hj23j287"

//"ka2hj2jp869"

2

2020年には、ブラウザー内のCrypto APIを使用して、暗号学的に強力なランダム値を生成できます。

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

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

Uint8ArrayCrypto.getRandomValuesの両方が、IE11を含むすべての主要なブラウザーでサポートされています


1

私自身の将来の参考のためにこのコードスニペットをここに投稿します(保証はありませんが、十分に「ユニーク」で十分です):

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

これは、数字だけで「chars」変数を変更したい場合、ほぼ保証された一意の32文字のキークライアント側を作成します。

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

これを使用して、JavaScriptで一意の番号を作成します

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

それは実際に動作します。:)


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'))//複雑になります

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


1

ノードではミリ秒がミリ秒ごとに更新されないため、以下が答えです。これにより、人間が読み取れる一意のチケット番号が生成されます。私はプログラミングとnodejsが初めてです。私が間違っていたら訂正してください。

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

@abarberによって提案されたソリューション(new Date()).getTime()は、ミリ秒のウィンドウがありtick、この間隔で衝突が発生した場合にaを合計するために使用するため、優れたソリューションであると想定すると、ここで実際に確認できるように組み込みを使用することを検討できます。

ここで、1/1000ウィンドウフレームで衝突が発生する可能性がある方法を以下に示します(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

次に、1/1000ウィンドウでの衝突を回避する提案された解決策を試します。

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

つまりprocess.nextTick、イベントループで呼び出されるノードのような関数を単一として使用することを検討することができます。これtickについては、ここで詳しく説明します。もちろんブラウザにはありませんprocess.nextTickので、どうやってそれを行うかを理解する必要があります。 この実装では、インストールされnextTickているブラウザでI / Oに最も近い機能を使用してブラウザに機能をsetTimeout(fnc,0)setImmediate(fnc)window.requestAnimationFrame。ここで提案したように、を追加することもできwindow.postMessageますがaddEventListener、も必要なので、読者に任せます。私は元のモジュールのバージョンを変更して、ここでそれをより簡単に保つようにしました:

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

したがって、1/1000ウィンドウにあります。

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

0

おそらくgetTime()またはvalueOf()を使用する方が良いでしょうが、このようにして、一意の数値と人間が理解できる数値(日付と時刻を表す)を返します。

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

簡単で常にユニークな価値を得る:

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

0

私はこのようにしました

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

上記の#Marcelo Lazaroniソリューションを参照して

Date.now() + Math.random()

この1567507511939.4558(小数点以下4桁に制限)などの数値を返し、0.1%ごとに一意でない数値(または衝突)を返します。

toString()を追加するとこれが修正されます

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

「15675096840820.04510962122198503」(文字列)を返し、さらに「遅い」ため、「同じ」ミリ秒を取得できません。


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

サンプル結果 "k3jobnvt_15750033412250_18299601769317408"


0

を使用してtoString(36)、少し遅いですが、これはより速くてユニークなソリューションです:

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

0

一意の番号を取得するには:

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

例:

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

以下を使用して長さを変更できます。

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

質問では、ランダムな文字列ではなく、一意の番号を求めました。
tshimkus

-1

別の数値を生成することが100%保証されています...

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>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.