一种生成有序的GUID字符串的代码实现(TypeScript)

以下代码用于生成有序的GUID字符串。

使用方法为:new OrderedGUIDGenerator().NewGuid()即可生成根据时间排序的Guid字符串。


/**
 * 用于生成根据时间戳附加随机数确定的有序GUID值
 * 使用方法:var orderedGuid=new OrderedGUIDGenerator().newGuid()。如果将newGuid()方法改为静态方法,即加上static,则使用方法为var orderedGuid=OrderedGUIDGenerator.newGuid()
 */
export default class OrderedGUIDGenerator
 {
    //生成的Guid的格式为:dddddddd-dddd-Mddd-Ndrr-rrrrrrrrrrrr
    // - M = RFC 版本(version), 这里取为4
    // - N = RFC 变体(variant),这里固定为8
    // - d = 从公元1年1月1日0时至今的时间总长(以100ns为单位)
    // - r = 随机数(random bytes)

	
    private static readonly DIFF:bigint=62135596800000000000n;  //从公元1年1月1日0时0分0秒到公元1970年1月1日0时0分0秒的纳秒数
    //nodeVitualStartTime表示node运行时启动时的纳秒数(从公元1年1月1日0时0分0秒算起)。资料显示,process.hrtime.bigint()方法计算的是方法调用时刻与node启动时的时间差(ns)
	private static readonly nodeVitualStartTime:bigint = BigInt(Date.now()) * 1000000n+OrderedGUIDGenerator.DIFF-process.hrtime.bigint();    
   
   
    private static readonly version = 4;//RFC版本号M,这里用4
    private static readonly variant = 8; //RFC变体N,这里用8
    private static readonly filterHighBit = 0b00001111;
    private  static readonly filterLowBit = 0b11110000;
	//获取从公元1年1月1日0时0分0秒开始的纳秒数
	private static nanoTime():bigint {return  OrderedGUIDGenerator.nodeVitualStartTime+process.hrtime.bigint()};

	/***********
     * 用于生成Guid字符串的方法
     * @param 无参数
     */
	public static newGuid():string {
      
            let nanoSeconds=this.nanoTime();

            const ticks:bigint=nanoSeconds/100n;    //获得以100ns为单位的时间
          
            //不再使用下面这句,因为测试过程中经常只是00,后续直接用随机数来代替
            //  const nanoEnds:bigint=nanoSeconds%100n; //100ns的尾数(即nanaSconds的最后两位数字,也就是十位数+个位数),用于填充guidBytes数组的第10个元素

            
                        

            let guidBytes:string[] = [];//guid数组,共有16个元素
    
       
            let ticksHex=ticks.toString(16).padStart(16,"0");//将ticks数据转换为16进制字符串,转换后应该有16字节,若不足16字节,头部用0填充
    
            for(let i=0;i<6;i++)    //guidBytes【0】~guidBytes【5】
                {
                    guidBytes.push(ticksHex.substring(i*2,i*2+2))
                }
         
            let ticksHexForUintPos6=ticksHex.substring(12,14);
            let ticksHexForUintPos7=ticksHex.substring(14,16);
            let timeStampArrayPos6=parseInt(ticksHexForUintPos6,16),timeStampArrayPos7=parseInt(ticksHexForUintPos7,16);
    
            //以下三行代码通过移位计算确定第7-第9个字节的数据
            guidBytes.push(((OrderedGUIDGenerator.version<<4)|((timeStampArrayPos6&OrderedGUIDGenerator.filterLowBit)>>4)).toString(16).padStart(2,'0'));  //guidBytes【6】 ;  高4位为版本 | 低4位取时间戳序号[6]的元素的高4位
            guidBytes.push((((timeStampArrayPos6&OrderedGUIDGenerator.filterHighBit)<<4)|((timeStampArrayPos7&OrderedGUIDGenerator.filterLowBit)>>4)).toString(16).padStart(2,'0')); //guidBytes【7】 ;高4位取:[6]低4位 | 低4位取:[7]高4位
            guidBytes.push(((OrderedGUIDGenerator.variant<<4)|(timeStampArrayPos7&OrderedGUIDGenerator.filterHighBit)).toString(16).padStart(2,'0')); // guidBytes【8】;高4位为:变体 | 低4位取:[7]低4位
    
          
            //第10个字节采用nanosecond%100,即最后两位数字的值来填充
            //guidBytes.push(Number(nanoEnds).toString(16).padStart(2,'0'));    // guidBytes[9]
          
          
          
            //以下这段代码通过随机数填充guidBytes尾部第10-16个元素(共14个字符,可以填充7个元素,即guidBytes[9]~guidBytes[15])
            //***以下这句代码生成14个字符的随机字符串,由于一次random()的字符数可能不足14个,所以用2次,并通过substring(2)去掉头部的两个字符"0."
            let randomString= (Math.random().toString(16).substring(2)+Math.random().toString(16).substring(2)).padStart(14,'0').substring(0,14);  
            for(let i=0;i<7;i++)             //将生成的字符复制到guidBytes数组的尾部7个元素位置 guidBytes[9]~guidBytes[15]
            {
                let randomUnit8Str=randomString.substring(2*i,2*i+2);
                guidBytes.push(randomUnit8Str);          //  guidBytes[9]~guidBytes[15]
            }



            let g=guidBytes;   //此处不必要,仅仅是用短的变量g,以便于下一句字符串拼接起来少写点字符,一行能放下
         
            let guidStr=g[0]+g[1]+g[2]+g[3]+"-"+g[4]+g[5]+"-"+g[6]+g[7]+"-"+g[8]+g[9]+"-"+g[10]+g[11]+g[12]+g[13]+g[14]+g[15];

			return guidStr;
		};

    }


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值