使用Javascript时间创建唯一数字

137

我需要使用JavaScript动态生成唯一的ID号码。过去,我是通过使用时间来创建一个数字来实现这一点的。该数字由四位数年份、两位数月份、两位数日期、两位数小时、两位数分钟、两位数秒和三位数毫秒组成。因此它看起来像这样:20111104103912732... 这足以提供我所需的唯一数字的确定性。

已经有一段时间了,我没有这个代码了。是否有人可以提供这个代码,或者有更好的建议来生成唯一ID?


5
可能是如何在Javascript中创建GUID / UUID?的重复问题。 - August Lilleaas
你考虑过使用 new Date().toISOString() 吗? - Anna B
39个回答

1

试试这个

    function generateId() {
    return +new Date();
}

然后将其赋值给变量

const uniqueId = generateId();

1
我在寻找一种简单的UID生成技术,同时也可排序(以便可以按UID顺序排列项目并按创建/ UID生成顺序显示)。大多数(所有?)解决方案的主要问题在于它们要么依赖于毫秒级精度(最好)== 冲突(!),要么是伪随机数== 冲突(!)&& 非可排序(!)。
下面的技术使用微秒精度(如果可用)(即不在使用指纹识别防护技术的情况下,例如Firefox),结合一个递增的、有状态的后缀。对于大量ID来说,它并不完美,或者特别高效(请参见下面的100万个示例),但它有效且可逆。

// return a uid, sortable by creation order
let increment;
let tuidPrev;

const uid = (uidPrev) => {
  // get current time to microsecond precision (if available) and remove decimals
  const tuid = ((performance.timing.navigationStart + performance.now()) * 1000)
    // convert timestamp to base36 string
    .toString(36);

  // previous uid has been provided (stateful)
  if (uidPrev) {
    tuidPrev = uidPrev.slice(0, 10);
    increment = uidPrev.length > 10 ? parseInt(uidPrev.slice(10), 36) : 0;
  }

  // if tuid is changed reset the increment
  if (tuid !== tuidPrev) {
    tuidPrev = tuid;
    increment = 0;
  }

  // return timed uid + suffix (4^36 values) === very unique id!
  return tuid + ('000' + (increment++).toString(36)).slice(-4);
}


// EXAMPLE (check the console!)
const iterations = 1000000;
const uids = [];
const uidMap = {};
const timeMap = {}
const microMap = {};
let time = performance.now();
for (let i = 0; i < iterations; i++) {
  const id = uid();
  uids.push(id);
  uidMap[id] = i;
  timeMap[Date.now()] = i;
  microMap[performance.now()] = i;
}

console.log(`Time taken: ${performance.now() - time}ms`);
console.log('Unique IDs:', Object.keys(uidMap).length.toLocaleString());
console.log('Clashing timestamps:', (iterations - Object.keys(timeMap).length).toLocaleString());
console.log('Clashing microseconds:', (iterations - Object.keys(microMap).length).toLocaleString());
console.log('Sortable:', !uids.slice().sort().find((id, i) => uids[i] !== id))


1
我通常生成唯一ID的方法是使用 Date.now();
const ID = Date.now();
console.log(ID);

另一种方法是使用一个名为idgp的库,可以通过npm安装。
链接: https://www.npmjs.com/package/idgp

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

样例结果为"k3jobnvt_15750033412250_18299601769317408"


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
也许更好的方法是使用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

假设@abarber提出的解决方案是一个好的解决方案,因为它使用(new Date()).getTime(),所以它有毫秒级的时间窗口,并在此间隔内发生冲突时加上tick,我们可以考虑使用内置的方法,正如我们在这里清楚地看到的那样:

首先,我们可以看到在使用(new Date()).getTime()时,1/1000窗口框架中可能会发生冲突:

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

添加我的看法是因为我想要一个 UID 的解决方案:

  • 可能是唯一的
  • 易读(可用于 URL)
  • 可以按创建日期排序
const uid = new Date().toISOString().replaceAll(/[-:TZ]/g, '.') + Math.random().toString().substring(2,7)
// '2022.04.15.03.56.36.197.50167'

注意:您可以调整子字符串的第二个参数以增加唯一性的机会,但这将使uid变长。具体取决于您的使用情况。


0

简单易用,总是获得唯一值:

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

0

即使在快速循环内部,这也返回唯一的值。

当然,这可以进一步改进

const getUniqueValue = (strength = 2, int=false) => {
    
    const u = () => (Math.random() * 10000).toString().replace('.','');
    
    let r = '';
    
    for (let i=0; i < strength; i++) {
        r += u();
    }
    
    return (int) ? parseInt(r) : r;
}

[1,2,3,5,6,7,8,9,10].map(item => console.log(getUniqueValue()));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接