【JavaScript】身份证号码合规性校验(支持18位、15位)

【JavaScript】身份号码(同时支持18位号码、15位号码)合规性校验

一、身份证号码校验

这个方法共分为4个部分,分别对身份证号码的格式和长度、前2位省份编码、出生日期、18位号码的校验码进行校验,其中每部分都能够单独拿出来使用,看对于数据的要求了。完整代码在最后。

1、校验身份证号码的格式和长度

首先校验身份证号码的格式和长度,若对于数据质量要求不高,则校验完格式就能满足需求,起码输入的数据格式是符合身份证号码要求的,15位号码全部为数字,18位号码前17位是数字,第18位是数字或者X.

// 1.校验身份证号格式和长度
const regPsidno = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[X])$)$/
    if (!regPsidno.test(psidno)) {
      return false
    }

2、校验前两位的省份编码是否正确

第二部分对身份证号码的前2位省份编码进行校验,没有01开头的身份证号,这部分校验就是为了防止这种号码的输入。

// 2.校验前两位的省份编码是否正确
    const province = { 11: '北京', 12: '天津', 13: '河北', 14: '山西', 15: '内蒙古', 21: '辽宁', 22: '吉林', 23: '黑龙江 ', 31: '上海', 32: '江苏', 33: '浙江', 34: '安徽', 35: '福建', 36: '江西', 37: '山东', 41: '河南', 42: '湖北 ', 43: '湖南', 44: '广东', 45: '广西', 46: '海南', 50: '重庆', 51: '四川', 52: '贵州', 53: '云南', 54: '西藏 ', 61: '陕西', 62: '甘肃', 63: '青海', 64: '宁夏', 65: '新疆', 71: '台湾', 81: '香港', 82: '澳门', 91: '国外' }
    if (!province[Number(psidno.slice(0, 2))]) {
      return false
    }

3、校验出生日期

第三步校验身份证号码中的出生日期是否合理,这部分校验是为了防止随便编一个出生日期为明年或12月32号的身份证号但符合编码格式的号码通过校验。

 // 3.校验出生日期
    if (psidno.length === 15) {
      // 15位号码 省(2位)市(2位)县(2位)年(2位)月(2位)日(2位)校验码(3位)
      const reg = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/)
      const arrSplit = psidno.match(reg)
      // 15位号码在年份前补 19 或 20
      const year = Number(arrSplit[2].charAt(0)) > 0 ? '19' + arrSplit[2] : '20' + arrSplit[2]
      const month = arrSplit[3]
      const day = arrSplit[4]
      if (!validateBirthday(year, month, day)) {
        return false
      }
    } else if (psidno.length === 18) {
      // 18位号码 省(2位)市(2位)县(2位)年(4位)月(2位)日(2位)校验码(4位)
      const reg = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/)
      const arrSplit = psidno.match(reg)
      const year = arrSplit[2]
      const month = arrSplit[3]
      const day = arrSplit[4]
      if (!validateBirthday(year, month, day)) {
        return false
      }
    } else {
      return false
    }
    // 校验出生日期是否合理
    function validateBirthday(year, month, day) {
      year = Number(year) // 年
      month = Number(month) // 月
      day = Number(day) // 日
      const nowTime = new Date().getTime() // 当前时间戳
      const birthTime = new Date(`${year}-${month}-${day}`).getTime() // 获取出生日期的时间戳
      // 不能是明天出生的吧
      if (birthTime > nowTime) {
        return false
      }
      // 一般人活不到150岁吧
      const nowYear = new Date().getFullYear()
      if ((nowYear - year) > 150) {
        return false
      }
      // 不能是13月出生的吧
      if (month < 1 || month > 12) {
        return false
      }
      // 不能是2月30号、4月31号、5月32号出生的吧
      const date = new Date(year, month, 0) // 获取当月的最后一天
      if (day < 1 || day > date.getDate()) {
        return false
      }
      return true
    }

4、校验18位号码生成的校验码

第四部分校验18位号码生成的校验码是否是正确的,通过了这个校验,才说明输入的是一个真的身份证号。

// 4.18位号码时校验生成的校验码
    if (psidno.length === 18) {
      const Wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] // 加权因子
      const parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'] // 校验码
      let sum = 0
      for (let i = 0; i < 17; i++) {
        sum += Number(psidno.charAt(i)) * Wi[i]
      }
      if (parity[sum % 11] !== psidno[17]) {
        return false
      }
    }

二、完整代码

/**
     * @description : 校验身份证号是否合规(18位、15位)
     * @param        {String|Number} value
     * @return       {Boolean} true-合规 false-不合规
     */
  checkPsidno(value) {
    const psidno = String(value)
    // 1.校验身份证号格式和长度
    const regPsidno = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[X])$)$/
    if (!regPsidno.test(psidno)) {
      return false
    }
    // 2.校验前两位的省份编码是否正确
    const province = { 11: '北京', 12: '天津', 13: '河北', 14: '山西', 15: '内蒙古', 21: '辽宁', 22: '吉林', 23: '黑龙江 ', 31: '上海', 32: '江苏', 33: '浙江', 34: '安徽', 35: '福建', 36: '江西', 37: '山东', 41: '河南', 42: '湖北 ', 43: '湖南', 44: '广东', 45: '广西', 46: '海南', 50: '重庆', 51: '四川', 52: '贵州', 53: '云南', 54: '西藏 ', 61: '陕西', 62: '甘肃', 63: '青海', 64: '宁夏', 65: '新疆', 71: '台湾', 81: '香港', 82: '澳门', 91: '国外' }
    if (!province[Number(psidno.slice(0, 2))]) {
      return false
    }
    // 3.校验出生日期
    if (psidno.length === 15) {
      // 15位号码 省(2位)市(2位)县(2位)年(2位)月(2位)日(2位)校验码(3位)
      const reg = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/)
      const arrSplit = psidno.match(reg)
      // 15位号码在年份前补 19 或 20
      const year = Number(arrSplit[2].charAt(0)) > 0 ? '19' + arrSplit[2] : '20' + arrSplit[2]
      const month = arrSplit[3]
      const day = arrSplit[4]
      if (!validateBirthday(year, month, day)) {
        return false
      }
    } else if (psidno.length === 18) {
      // 18位号码 省(2位)市(2位)县(2位)年(4位)月(2位)日(2位)校验码(4位)
      const reg = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/)
      const arrSplit = psidno.match(reg)
      const year = arrSplit[2]
      const month = arrSplit[3]
      const day = arrSplit[4]
      if (!validateBirthday(year, month, day)) {
        return false
      }
    } else {
      return false
    }
    // 校验出生日期是否合理
    function validateBirthday(year, month, day) {
      year = Number(year) // 年
      month = Number(month) // 月
      day = Number(day) // 日
      const nowTime = new Date().getTime() // 当前时间戳
      const birthTime = new Date(`${year}-${month}-${day}`).getTime() // 获取出生日期的时间戳
      // 不能是明天出生的吧
      if (birthTime > nowTime) {
        return false
      }
      // 一般人活不到150岁吧
      const nowYear = new Date().getFullYear()
      if ((nowYear - year) > 150) {
        return false
      }
      // 不能是13月出生的吧
      if (month < 1 || month > 12) {
        return false
      }
      // 不能是2月30号、4月31号、5月32号出生的吧
      const date = new Date(year, month, 0) // 获取当月的最后一天
      if (day < 1 || day > date.getDate()) {
        return false
      }
      return true
    }
    // 4.18位号码校验生成的校验码
    if (psidno.length === 18) {
      const Wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] // 加权因子
      const parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'] // 校验码
      let sum = 0
      for (let i = 0; i < 17; i++) {
        sum += Number(psidno.charAt(i)) * Wi[i]
      }
      if (parity[sum % 11] !== psidno[17]) {
        return false
      }
    }
    return true
  }

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马大头0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值