js 获取不重复11位-12位-13位-14位-及n位序列号

js 获取不重复11位-12位-13位-14位-及n位序列号

在生成不重复ID号的方法中有各种方法,如使用随机数,时间戳等等。还有下载现成的如只需下载cuid使用也非常方便,下载地址:https://github.com/paralleldrive/cuid虽然让ID号变的唯一不重复,但它却变的没有任何意义,一眼看上去没有任何规律可寻。而通过ID号来查找数据变的不能,唯一能找到此ID的方法就是通过其它字段查找来获取此ID号,有一种需求是使用ID来查找所在产品是那一天生产的是几时生产的,通过上述方法是无法获得的,除非在数据库中增加时间字段,这无疑又增加了数据库的体积,本文提供一种方法来阐释11位及以上不重复数字的生成方法。

1、11位数字序列号的结构

1.1、11位数字的两层结构

首先要生成11位数字,并且具有其意义,我们可以把11位数字分成两层来研究。如图(1)所示。
在这里插入图片描述

  • 第一层由六位数字组成分别是年月日,年取后两位
  • 第二层有五位数字理论上可以组成00000至99999的组合
  • 注意图片中的横杠是方便分析所画实际数据中并无此杠

1.2、第一层的数字结构

第一层由六位数字组成,又分为三层。每层由2位数字组成。如图(2)所示:
在这里插入图片描述

  • 注意图片中的空格是方便分析所画实际数据中并无空格
  • 第一层由年的后两位组成。如2022年,组成后为22,理论上可以00-99也就是一百年的组合,对于数据结构来说一百年足够了
  • 第二层由月组成,不足两位的补零,如1月,组成后为01。
  • 第三层由日组成,不足两位的补零,如1号,组成后为01。

1.3、第二层的数字结构

11位数字不重复的第二层由五位数字组成。

2、11位不重复数字结构适用范围

对于11位不重复ID理论上可以组成百亿的排列组合,它可以提供百年需求,每日可提供00000至99999个数据,但实际情况却远远达不到,也就限制了它的适用范围。本例所使用的是时间戳的形式来提供不重复序列,使用当日23:59:59减当前时间的方式来拿到不重复序列,从每日的00:00:00:到23:59:59可以生成86400个数字序列号,(注意是每秒)。但实际应用中不可能一天24小时时刻在使用序列号,也就是有空闲时间,这此空闲时间就造成了序列号的浪费。就拿每天8小时工作日来说一天最多也就提供10800序列号,每小时也只能提供3600个序列号,这也只是理论上计算所得。所以此算法只能提供一些每天不超过10000的数据量的项目使用。虽然这种算法有其局限性,但却有相当大的需求,如一个单位的档案管理,一个工厂每天生产的产品不足10000个产品的客户,如果24小时生产它却可以非常的适用。

3、11位不重复数字序列的实现

以下是实现11位不重复数的方法。实现这种方法其实也十分简单。

  • 第一层数据获取:通过计算当前日期算出年月日,年取后两位,月不足两位前面加零,日也同样的方法,来组合成。
  • 第二层数据获取:是通过获取时间戳的方式来得到。
    1、获取当日凌晨0:00:00(零时整)的时间戳;
    2、获取当日23:59:59时间戳;
    3、获取当前时间戳;
    4、当前时间戳与23:59:59值相减之后就可以得到后5位的第二层数据。
//生成不重复11位序列号
function serial_num_11() {
    
    
    var d = new Date();
    var year = d.getFullYear();
    var month = d.getMonth() + 1;
    var date = d.getDate();
    var day = d.getDay();
    year = (year + "").substring(2);
    if (month <= 9) {
    
    
      month = "0" + month;
    } else if (date <= 9) {
    
    
      date = "0" + date;
    }
    //获取当日凌晨0:00:00(零时整)
    let startTime = parseInt(new Date(new Date().toLocaleDateString()).getTime());
    //获取当日23:59:59
    let endTime = startTime + (24 * 60 * 60 * 1000 - 1);
    //获取当前时间戳
    let currentTime = parseInt(new Date().getTime());
    let remainTime = parseInt((parseInt(endTime) - parseInt(currentTime)) / 1000);
    let time;
    if (parseInt(currentTime) > parseInt(startTime)) {
    
    
      if (remainTime < 10) {
    
    
        time = "0000" + remainTime.toString();
      }
      if (remainTime < 100 && remainTime >= 10) {
    
    
        time = "000" + remainTime.toString();
      }
      if (remainTime < 1000 && remainTime >= 100) {
    
    
        time = "00" + remainTime.toString();
      }
      if (remainTime < 10000 && remainTime >= 1000) {
    
    
        time = "0" + remainTime.toString();
      }
      if (remainTime >= 10000) {
    
    
        time = remainTime.toString();
      }
      var id = year + month + date + time;
      return id;
    }
  
  }

2、时间同步

通过上述方法得到的11位序列号,细心的道友可能会发现,如果时间的不同步,会给后端带来诸多的麻烦。有造成序号相同的情况发生,这就要求服务端与客户端的时间同步,这在工业生产中,时间同步是一项基本要求,在这里提出来是防止错误的使用。

2、12位序列号的产生

2.1、12位序列号产生方法一

对于12位序列号的产生就相对非常容易实现了,举一个非常简单的例子,如果你有十几条生产线同时生产同一产品,也需要序列号来标识产品的生产日期生产时间,但是那一条生产线生产的却不知道这样非常容易造成混淆,方法其实非常简单,只需要在11位序列号前面加一个字每就可以满足生产需要。这样一来数字结构就变成三层如图(3)所示:
在这里插入图片描述

  • 注意图片中的横杠是方便分析所画实际数据中并无此杠

2.3 12位序列号产生方式二

12位序列代码产生方式二也非常简单,在函数中求差值部分除以100。要知道每天开始与结束值是用毫秒来计算的,而上述11位方法中除以1000可以精确到秒的。而每天开始到结束的毫秒数为86400000个。除以100就是去除后而两位数由86400000变为864000六位数与第一层组合正好为12位数,其实上是去除毫秒数的后两位,取值范围00-99间,也就是十分之一秒,每天可提供864000个序列号这比11位序列号大大的增加10倍。
数据结构如图(4)所示:
在这里插入图片描述

由上图4所示:

  • 第一层由六位数组成,(第一层下又分三层每两位数为一层共有三个分层见图2所示)。
  • 第二层由六位数组成,每天可提供864000个组合。每小时可提供36000序列。
  • 注意图片中的横杠是方便分析所画实际数据中并无此杠

代码如下:

//生成不重复12位序列号
function serial_num_12() {
    
    
    var d = new Date();
    var year = d.getFullYear();
    var month = d.getMonth() + 1;
    var date = d.getDate();
    var day = d.getDay();
    year = (year + "").substring(2);
    if (month <= 9) {
    
    
        month = "0" + month;
    } else if (date <= 9) {
    
    
        date = "0" + date;
    }
    //获取当日凌晨0:00:00(零时整)
    let startTime = parseInt(new Date(new Date().toLocaleDateString()).getTime());
    //获取当日23:59:59
    let endTime = startTime + (24 * 60 * 60 * 1000 - 1);
    //获取当前时间戳
    let currentTime = parseInt(new Date().getTime());
    let remainTime = parseInt((parseInt(endTime) - parseInt(currentTime)) / 100);
    let time;
    if (parseInt(currentTime) > parseInt(startTime)) {
    
    
        if (remainTime < 10) {
    
    
            time = "00000" + remainTime.toString();
        }
        if (remainTime < 100 && remainTime >= 10) {
    
    
            time = "0000" + remainTime.toString();
        }
        if (remainTime < 1000 && remainTime >= 100) {
    
    
            time = "000" + remainTime.toString();
        }
        if (remainTime < 10000 && remainTime >= 1000) {
    
    
            time = "00" + remainTime.toString();
        }
        if (remainTime < 100000 && remainTime >= 10000) {
    
    
            time = "0" + remainTime.toString();
        }
        if (remainTime >= 100000) {
    
    
            time = remainTime.toString();

        }
        var id = year + month + date + time;       
        return id;
    }

}
}

3、13位序列号的生成

13位数字组成同上方法一样。数据结构如图(5)所示
在这里插入图片描述

  • 第一层由六位数组成,(第一层下又分三层每两位数为一层共有三个分层见图2所示)。
  • 第二层由七位数组成,每天可提供8640000个组合。每小时可提供360000序列。
  • 注意图片中的横杠是方便分析所画实际数据中并无此杠

下面展示一些 内联代码片

//生成不重复13位序列号
function serial_num_13() {
    
    
    var d = new Date();
    var year = d.getFullYear();
    var month = d.getMonth() + 1;
    var date = d.getDate();
    var day = d.getDay();
    year = (year + "").substring(2);
    if (month <= 9) {
    
    
        month = "0" + month;
    } else if (date <= 9) {
    
    
        date = "0" + date;
    }
    //获取当日凌晨0:00:00(零时整)
    let startTime = parseInt(new Date(new Date().toLocaleDateString()).getTime());
    //获取当日23:59:59
    let endTime = startTime + (24 * 60 * 60 * 1000 - 1);
    //获取当前时间戳
    let currentTime = parseInt(new Date().getTime());
    let remainTime = parseInt((parseInt(endTime) - parseInt(currentTime)) / 10);
    console.log('剩余时间', remainTime)
    let time;
    if (parseInt(currentTime) > parseInt(startTime)) {
    
    
        if (remainTime < 10) {
    
    
            time = "000000" + remainTime.toString();
        }
        if (remainTime < 100 && remainTime >= 10) {
    
    
            time = "00000" + remainTime.toString();
        }
        if (remainTime < 1000 && remainTime >= 100) {
    
    
            time = "0000" + remainTime.toString();
        }
        if (remainTime < 10000 && remainTime >= 1000) {
    
    
            time = "000" + remainTime.toString();
        }
        if (remainTime < 100000 && remainTime >= 10000) {
    
    
            time = "00" + remainTime.toString();
        }
        if (remainTime < 1000000 && remainTime >= 100000) {
    
    
            time = "0" + remainTime.toString();
        }
        if (remainTime >= 1000000) {
    
    
            time = remainTime.toString();

        }
        var id = year + month + date + time;
        console.log(id)
        return id;
    }

}

4、14位序列号的生成

如上原理。数据结构如图(6)
在这里插入图片描述

  • 第一层由六位数组成,(第一层下又分三层每两位数为一层共有三个分层见图2所示)。
  • 第二层由八位数组成,每天可提供86400000个组合。每小时可提供3600000序列。

代码如下:

//生成不重复14位序列号
function serial_num_14() {
    
    
    var d = new Date();
    var year = d.getFullYear();
    var month = d.getMonth() + 1;
    var date = d.getDate();
    var day = d.getDay();
    year = (year + "").substring(2);
    if (month <= 9) {
    
    
        month = "0" + month;
    } else if (date <= 9) {
    
    
        date = "0" + date;
    }
    //获取当日凌晨0:00:00(零时整)
    let startTime = parseInt(new Date(new Date().toLocaleDateString()).getTime());
    //获取当日23:59:59
    let endTime = startTime + (24 * 60 * 60 * 1000 - 1);
    //获取当前时间戳
    let currentTime = parseInt(new Date().getTime());
    let remainTime = parseInt((parseInt(endTime) - parseInt(currentTime)));
    let time;
    if (parseInt(currentTime) > parseInt(startTime)) {
    
    
        if (remainTime < 10) {
    
    
            time = "0000000" + remainTime.toString();
        }
        if (remainTime < 100 && remainTime >= 10) {
    
    
            time = "000000" + remainTime.toString();
        }
        if (remainTime < 1000 && remainTime >= 100) {
    
    
            time = "00000" + remainTime.toString();
        }
        if (remainTime < 10000 && remainTime >= 1000) {
    
    
            time = "0000" + remainTime.toString();
        }
        if (remainTime < 100000 && remainTime >= 10000) {
    
    
            time = "000" + remainTime.toString();
        }
        if (remainTime < 1000000 && remainTime >= 100000) {
    
    
            time = "00" + remainTime.toString();
        }
        if (remainTime < 10000000 && remainTime >= 1000000) {
    
    
            time = "0" + remainTime.toString();
        }
        if (remainTime >= 10000000) {
    
    
            time = remainTime.toString();
        }
        var id = year + month + date + time;
        return id;
    }

}

5、N位数序列号的生成

前面所提到的生成方法,可以扩展为N多个序列号,这里主要提一下同一序列号的冲突,同一序列是否会产生答案是一定会的,如何避免这一冲突的产生,解决方法可以在序列号前面增加区划代码的方式来加以区分,这样可以大大减少同一序号产生的冲突,同一序号产生的原因是由多台设备同一时间所产生的序列号,解决方法无非如下几种:

  1. 序号前加区划代码
    序号前加识别号可以采用区划代码的方式,如中国有31个省市自治区,如前面加两位数字就可识别省
    如11代表北京市,63代表青海省具体见《全国区划代码表》。如要区别到城市只需四位数字,如昆明市的区划为5301。在全国区划代码中六位就可定位到街道。
  2. 序号前加IP地址:
    每一台电脑的IP地址是不同的可以将IP地址号转换为数字或所在地区的区划代码加在前面,这样就避免了同号的冲突
  3. 序号前加字母:
    这样也可以区别同号冲突问题,在流水线做业的机械有多台,可以用字母在首位以区分避免同号冲突问题
  4. 后台再次验证也可以避免同号冲突问题。

6、总结

本章所讨论的内容只为数字编号附有其意义,随着编号长度增加适用范围也就越大,但不可避免的也有其局限性。这也要根据你所研究的项目来决定是否采用此方法,本篇只是提供了一种可能性,错误之外还望批评指正。如果你的项目是为单位员工的序号(id)编号大可采用此方法,因为员工入职那天就是此ID前6位,如果你是工厂产品出厂日期也可使用此方法,因为每一批产品的出厂日期,什么时间点加工出来的都可以倒查回去,包括产品质量批次出了问题也可以倒查。虽然数字编号方式不是全能的但也有一定的适用处。

猜你喜欢

转载自blog.csdn.net/weixin_43727933/article/details/127242899