Browse Source

Finish `IsValid` method

tags/v1.0.0
guanguans 3 years ago
parent
commit
e70138664f
5 changed files with 3429 additions and 3212 deletions
  1. +32
    -0
      Generator.go
  2. +87
    -0
      checker.go
  3. +3212
    -3212
      data/address_code.go
  4. +75
    -0
      helper.go
  5. +23
    -0
      id_validator.go

+ 32
- 0
Generator.go View File

@@ -0,0 +1,32 @@
package id_validator

import (
"math"
"strconv"
"strings"
)

func GeneratorCheckBit(body string) string {
// 位置加权
var posWeight [19]float64
for i := 2; i < 19; i++ {
weight := int(math.Pow(2, float64(i-1))) % 11
posWeight[i] = float64(weight)
}

// 累身份证号 body 部分与位置加权的积
bodySum := 0
bodyArray := strings.Split(body, "")
count := len(bodyArray)
for i := 0; i < count; i++ {
bodySubStr, _ := strconv.Atoi(bodyArray[i])
bodySum += bodySubStr * int(posWeight[18-i])
}

// 生成校验码
checkBit := (12 - (bodySum % 11)) % 11
if checkBit == 10 {
return "X"
}
return strconv.Itoa(checkBit)
}

+ 87
- 0
checker.go View File

@@ -0,0 +1,87 @@
package id_validator

import (
"regexp"
"strconv"
"strings"
"time"
)

// 检查ID参数
func CheckIdArgument(id string) bool {
return len(GenerateType(id)) != 0
}

// 生成数据
func GenerateType(id string) map[string]string {
lowerId := strings.ToLower(id)

if len(lowerId) == 15 {
return GenerateShortType(id)
}

if len(lowerId) == 18 {
return GenerateLongType(id)
}

return map[string]string{}
}

// 生成短数据
func GenerateShortType(id string) map[string]string {
mustCompile := regexp.MustCompile("(.{6})(.{6})(.{3})")
subMatch := mustCompile.FindStringSubmatch(id)

return map[string]string{
"body": subMatch[0],
"addressCode": subMatch[1],
"birthdayCode": "19" + subMatch[2],
"order": subMatch[3],
"checkBit": "",
"type": "15",
}
}

// 生成长数据
func GenerateLongType(id string) map[string]string {
mustCompile := regexp.MustCompile("((.{6})(.{8})(.{3}))(.)")
subMatch := mustCompile.FindStringSubmatch(id)

return map[string]string{
"body": subMatch[1],
"addressCode": subMatch[2],
"birthdayCode": subMatch[3],
"order": subMatch[4],
"checkBit": subMatch[5],
"type": "18",
}
}

// 检查地址码
func CheckAddressCode(addressCode string, birthdayCode string) bool {
addressInfo := GetAddressInfo(addressCode, birthdayCode)
if addressInfo["province"] == "" {
return false
}
return true
}

// 检查出生日期码
func CheckBirthdayCode(birthdayCode string) bool {
year, _ := strconv.Atoi(Substr(birthdayCode, 0, 4))
if year < 1800 {
return false
}

_, error := time.Parse("20060102", birthdayCode)
if error != nil {
return false
}

return true
}

// 检查顺序码
func CheckOrderCode(orderCode string) bool {
return len(orderCode) == 3
}

+ 3212
- 3212
data/address_code.go
File diff suppressed because it is too large
View File


+ 75
- 0
helper.go View File

@@ -0,0 +1,75 @@
package id_validator

import (
"strconv"

"id-validator/data"
)

// 检查地址码
func GetAddressInfo(addressCode string, birthdayCode string) map[string]string {
addressInfo := map[string]string{
"province": "",
"city": "",
"district": "",
}

// 省级信息
provinceAddressCode := Substr(addressCode, 0, 2) + "0000"
addressInfo["province"] = GetAddress(provinceAddressCode, birthdayCode)

// 用于判断是否是港澳台居民居住证(8字开头)
firstCharacter := Substr(addressCode, 0, 1)
// 港澳台居民居住证无市级、县级信息
if firstCharacter == "8" {
return addressInfo
}

// 市级信息
cityAddressCode := Substr(addressCode, 0, 4) + "00"
addressInfo["city"] = GetAddress(cityAddressCode, birthdayCode)

// 县级信息
addressInfo["district"] = GetAddress(addressCode, birthdayCode)

return addressInfo
}

func GetAddress(addressCode string, birthdayCode string) string {
var address string

addressCodeStr, _ := strconv.Atoi(addressCode)
addressCodeTimeline := data.AddressCodeTimeline[addressCodeStr]

year := Substr(birthdayCode, 0, 4)
yearStr, _ := strconv.Atoi(year)

for key, val := range addressCodeTimeline {
if len(val) == 0 {
continue
}

startYear, _ := strconv.Atoi(val["start_year"])
if (key == 0 && yearStr < startYear) || yearStr >= startYear {
address = val["address"]
}
}

return address
}

// Substr 截取字符串
func Substr(source string, start int, end int) string {
var r = []rune(source)
length := len(r)

if start < 0 || end > length || start > end {
return ""
}

if start == 0 && end == length {
return source
}

return string(r[start:end])
}

+ 23
- 0
id_validator.go View File

@@ -0,0 +1,23 @@
package id_validator

// 验证身份证号合法性
func IsValid(id string) bool {
if !CheckIdArgument(id) {
return false
}

code := GenerateType(id)
if !CheckAddressCode(code["addressCode"], code["birthdayCode"]) || !CheckBirthdayCode(code["birthdayCode"]) || !CheckOrderCode(code["order"]) {
return false
}

// 15位身份证不含校验码
if code["type"] == "15" {
return true
}

// 验证:校验码
checkBit := GeneratorCheckBit(code["body"])

return code["checkBit"] == checkBit
}

Loading…
Cancel
Save