Создайте уникальный номер со временем javascript


96

Мне нужно на лету сгенерировать уникальные идентификационные номера с помощью javascript. Раньше я делал это, создавая число, используя время. Число будет состоять из четырехзначного года, двухзначного месяца, двухзначного дня, двухзначного часа, двухзначной минуты, двухзначной секунды и трехзначной миллисекунды. Это будет выглядеть примерно так: 20111104103912732 ... это даст достаточную уверенность в уникальном номере для моих целей.

Прошло много времени с тех пор, как я это сделал, а кода у меня больше нет. У кого-нибудь есть код для этого или есть лучшее предложение для создания уникального идентификатора?



Вы думали new Date().toISOString ()?
gaspard

Возможный дубликат Create GUID / UUID в JavaScript?
ebram khalil

Ответы:


67

Если вам просто нужен уникальный номер, тогда

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

79
Отметка времени должна быть возвращает число в диапазоне от 0 до 999. возвращает миллисекунд с 1 января 1970 года (нормальная временная метка). w3schools.com/jsref/jsref_obj_date.aspnew Date().getTime();date.getUTCMilliseconds()date.getTime()
Automatico,

8
-1, поскольку вопрос был об уникальном номере. Первый блок кода следует полностью опустить.
Андрей

Это может генерировать 2 уникальных значения:function foo1() {console.log(new Date().getUTCMilliseconds()); console.log(new Date().getUTCMilliseconds()); }
Шариков Владислав

10
getUTCMilliseconds The value returned by getUTCMilliseconds() is an integer between 0 and 999.. Это худшая идея для уникального идентификатора, первый абзац следует удалить.
gaspard

118

Лучшим подходом было бы:

new Date().valueOf();

вместо того

new Date().getUTCMilliseconds();

valueOf () - «скорее всего» уникальное число. http://www.w3schools.com/jsref/jsref_valueof_date.asp .


19
Это не уникальное число ... миллисекунды недостаточно детализированы, чтобы считаться уникальными.
Vamsi Mohan Jayanti

3
Или просто+new Date()
thdoan

1
Я просто запустил цикл for и получил повторяющиеся результаты с valueOf(). Я просто использую это - +performance.now().toString().replace('.', 7) developer.mozilla.org/en-US/docs/Web/API/Performance/now
Ицик Бен Хатта,

1
@ItzikBenHutta Получил в 3 раза больше стоимости. Использование многоядерного процессора, вероятно, состояние гонки с потоками.
that-ben

70

Самый короткий способ создать число, которое, как вы можете быть уверены, будет уникальным среди стольких отдельных экземпляров, о которых вы можете подумать, -

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 символов, что является приличным количеством энтропии. Хотя половина из них предсказуема.
Эрик Пукинскис

2
Это должен быть принятый ответ, так как при попытке других ответов с более высоким рейтингом я получил в 2 и даже 3 раза одно и то же значение подряд при вызове из асинхронной функции. Кажется, это обеспечивает достаточную случайность для стандартного 8-ядерного процессора, чтобы генерировать 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
что, если это вызывается дважды за одну и ту же миллисекунду?
TBE

1
В самом деле, но это было нормально для op: «это дало бы достаточную уверенность в уникальном номере для моих целей».
Август Лиллеаас

17

Вот что я делаю, когда мне нужно что-то меньшее, чем связка чисел, - меняю базу.

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

1
@blushrt правда, может вызывать редкие коллизии. Вы можете установить метку времени, используя что-то вроде code.google.com/p/crypto-js , но для моих целей это было «достаточно уникально» и, что более важно, быстрее.
frumbert

@frumbert, это зависит от обстоятельств. MD5 также не устойчив к столкновениям. Но в вашем случае у меня очень быстро возникли проблемы из-за toString (36), который, как я полагаю, преобразует числовое значение в его представление ascii, хотя не уверен, но я вижу проблему, если вы вызываете свой генератор uuid достаточно часто, только последние 3 символы меняются, поэтому высока вероятность столкновения. У вас будет гораздо больше шансов, если вы просто будете придерживаться новых вызовов Date.getTime (). Но, эй, если это сработало для ваших целей, нет проблем, мне это нужно для некоторых уникальных идентификаторов только для моего кода на стороне клиента, в итоге я использовал uuid node lib.
blushrt

Я люблю это! Я настроил его так, (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

Вы также можете использовать что-то более сложное, например cuid , puid или shorttid, чтобы сгенерировать нечисловое число.


1
Мне кажется, что добавление случайных чисел на самом деле сделает это БЕСПЛАТНЫМ доказательством. С помощью только метки времени необходимо создать два числа в одной и той же миллисекунде, чтобы они были одинаковыми. Сложив два случайных числа, вы создали множество комбинаций чисел из-за математики, которые могут дать тот же результат при умножении. Я знаю, что это маловероятно, но ... не так ли?
Фил

Хм да. Возможно, лучше всего подойдет комбинация Моего ответа и ответа аббревиатуры.
Стивен Вашон

Обновил свой ответ. Спасибо за мысль.
Стивен Вашон

2
Хорошие усилия, я не пытаюсь уловить свой ответ ... но это новое решение на самом деле не решает проблему "более одного идентификатора, созданного за одну миллисекунду", потому что, я знаю ... это javascript на стороне КЛИЕНТА. Если другой пользователь создал номер в ту же самую миллисекунду, он не будет отражен в uniqueNumber.previous для «другого» пользователя. Если вы не храните его где-нибудь на сервере и не проверяете уникальность ... просто решение, основанное исключительно на js, не может быть уверенным, что оно создает уникальный номер.
Фил

Что ж, это была бы более сложная система, чем просто уникальный номер.
Стивен Вашон

12

я использую

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

Так что, если по какой-то причине код запускается одновременно, есть небольшая вероятность, что случайные числа будут такими же.


Не уверен, что new Date()это полезно. Вы можете получить одинаковые числа с двумя разными датами
JMaylin

1
Я имею в виду, как это лучше, чем просто делать Math.random()?
JMaylin

7

Это должно делать:

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

1
Полезно во многих случаях, хотя на самом деле это не создает чистых «уникальных» идентификаторов, если эта функция вызывается несколько раз за одну и ту же миллисекунду ... Но в любом случае, для взаимодействия с пользователем и пользовательским интерфейсом это хорошо.
Бенджамин Пьетт

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

output :: все числа уникальны

15598251485988384 155982514859810330 155982514859860737 155982514859882244 155982514859883316

уникальный номер без Math.random()

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

output :: Числа повторяются

1559825328327 1559825328327 1559825328327 1559825328328 1559825328328


4

Изучая онлайн, я придумал следующий объект, который создает уникальный идентификатор для каждой сессии:

        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, для меня ваше решение простое и понятное.
Камил Наджа

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

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

как Uint8Array, так и Crypto.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

Это создает почти гарантированно уникальный 32-символьный ключ на стороне клиента, если вы хотите, чтобы переменная "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

используйте это: для создания уникального номера в 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;
    }

Вызов 1: UniqueValue ('0')
Вызов 2: UniqueValue (UniqueValue ('0')) // будет сложным

Пример выходных данных:
for (var i = 0; i <10; i ++) {console.log (UniqueValue (UniqueValue ('0')));}
60950116113248802
26780116113248803
53920116113248803
35840116113248803
47430116113248803
35840116113248803
47430116113248803
41680113211803
47430116113248803
41680113211803 41680113211809


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в случае столкновений в этом интервале, мы могли бы рассмотреть возможность использования встроенного, как мы можем ясно видеть здесь в действии:

Во-первых, здесь мы можем увидеть, как могут быть столкновения в оконной раме 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функцию в браузере , используя самые близкие функции ввода / вывода в браузере, которые 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 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

0

простое решение, которое я нашел

var today = новая дата (). valueOf ();

console.log (сегодня);

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.