|
|
@@ -0,0 +1,174 @@ |
|
|
|
package id_validator |
|
|
|
|
|
|
|
import ( |
|
|
|
"fmt" |
|
|
|
"math" |
|
|
|
"math/rand" |
|
|
|
"regexp" |
|
|
|
"strconv" |
|
|
|
"strings" |
|
|
|
"time" |
|
|
|
|
|
|
|
"id-validator/data" |
|
|
|
) |
|
|
|
|
|
|
|
// 生成 Bit 码 |
|
|
|
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) |
|
|
|
} |
|
|
|
|
|
|
|
// 生成地址码 |
|
|
|
func GeneratorAddressCode(address string) string { |
|
|
|
var addressCodeInt int |
|
|
|
for code, addressStr := range data.AddressCode { |
|
|
|
if address == addressStr { |
|
|
|
addressCodeInt = code |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
addressCode := strconv.Itoa(addressCodeInt) |
|
|
|
|
|
|
|
classification := AddressCodeClassification(strconv.Itoa(addressCodeInt)) |
|
|
|
|
|
|
|
switch classification { |
|
|
|
case "country": |
|
|
|
// addressCode = GetRandAddressCode("\\d{4}(?!00)[0-9]{2}$") |
|
|
|
addressCode = GetRandAddressCode("\\d{4}(?)[0-9]{2}$") |
|
|
|
case "province": |
|
|
|
provinceCode := Substr(addressCode, 0, 2) |
|
|
|
// pattern := "^" + provinceCode + "\\d{2}(?!00)[0-9]{2}$" |
|
|
|
pattern := "^" + provinceCode + "\\d{2}(?)[0-9]{2}$" |
|
|
|
addressCode = GetRandAddressCode(pattern) |
|
|
|
case "city": |
|
|
|
cityCode := Substr(addressCode, 0, 4) |
|
|
|
// pattern := "^" + cityCode + "(?!00)[0-9]{2}$" |
|
|
|
pattern := "^" + cityCode + "(?)[0-9]{2}$" |
|
|
|
addressCode = GetRandAddressCode(pattern) |
|
|
|
} |
|
|
|
|
|
|
|
return addressCode |
|
|
|
} |
|
|
|
|
|
|
|
// 地址码分类 |
|
|
|
func AddressCodeClassification(addressCode string) string { |
|
|
|
// 全国 |
|
|
|
if addressCode == "" { |
|
|
|
return "country" |
|
|
|
} |
|
|
|
|
|
|
|
// 港澳台 |
|
|
|
if Substr(addressCode, 0, 1) == "8" { |
|
|
|
return "special" |
|
|
|
} |
|
|
|
|
|
|
|
// 省级 |
|
|
|
if Substr(addressCode, 2, 6) == "0000" { |
|
|
|
return "province" |
|
|
|
} |
|
|
|
|
|
|
|
// 市级 |
|
|
|
if Substr(addressCode, 4, 6) == "00" { |
|
|
|
return "city" |
|
|
|
} |
|
|
|
|
|
|
|
// 县级 |
|
|
|
return "district" |
|
|
|
} |
|
|
|
|
|
|
|
// 获取随机地址码 |
|
|
|
func GetRandAddressCode(pattern string) string { |
|
|
|
mustCompile := regexp.MustCompile(pattern) |
|
|
|
|
|
|
|
var keys []string |
|
|
|
for key, _ := range data.AddressCode { |
|
|
|
keyStr := strconv.Itoa(key) |
|
|
|
if mustCompile.MatchString(keyStr) && Substr(keyStr, 4, 6) != "00" { |
|
|
|
keys = append(keys, keyStr) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// initialize global pseudo random generator |
|
|
|
rand.Seed(time.Now().Unix()) |
|
|
|
randKey := rand.Intn(len(keys)) |
|
|
|
|
|
|
|
return keys[randKey] |
|
|
|
} |
|
|
|
|
|
|
|
// 生成出生日期码 |
|
|
|
func GeneratorBirthdayCode(birthday string) string { |
|
|
|
year, _ := strconv.Atoi(DatePad(Substr(birthday, 0, 4), "year")) |
|
|
|
month, _ := strconv.Atoi(DatePad(Substr(birthday, 4, 6), "month")) |
|
|
|
day, _ := strconv.Atoi(DatePad(Substr(birthday, 6, 8), "day")) |
|
|
|
|
|
|
|
nowYear := time.Now().Year() |
|
|
|
rand.Seed(time.Now().Unix()) |
|
|
|
if year < 1800 || year > nowYear { |
|
|
|
randYear := rand.Intn(nowYear-1950) + 1950 |
|
|
|
year, _ = strconv.Atoi(DatePad(strconv.Itoa(randYear), "year")) |
|
|
|
} |
|
|
|
if month < 1 || month > 12 { |
|
|
|
randMonth := rand.Intn(12-1) + 1 |
|
|
|
month, _ = strconv.Atoi(DatePad(strconv.Itoa(randMonth), "month")) |
|
|
|
} |
|
|
|
if day < 1 || day > 31 { |
|
|
|
randDay := rand.Intn(28-1) + 1 |
|
|
|
day, _ = strconv.Atoi(DatePad(strconv.Itoa(randDay), "day")) |
|
|
|
} |
|
|
|
|
|
|
|
birthdayStr := strconv.Itoa(year) + strconv.Itoa(month) + strconv.Itoa(day) |
|
|
|
_, error := time.Parse("20060102", birthdayStr) |
|
|
|
if error != nil { |
|
|
|
randYear := rand.Intn(nowYear-1950) + 1950 |
|
|
|
year, _ = strconv.Atoi(DatePad(strconv.Itoa(randYear), "year")) |
|
|
|
|
|
|
|
randMonth := rand.Intn(12-1) + 1 |
|
|
|
month, _ = strconv.Atoi(DatePad(strconv.Itoa(randMonth), "month")) |
|
|
|
|
|
|
|
randDay := rand.Intn(28-1) + 1 |
|
|
|
day, _ = strconv.Atoi(DatePad(strconv.Itoa(randDay), "day")) |
|
|
|
} |
|
|
|
|
|
|
|
return strconv.Itoa(year) + strconv.Itoa(month) + strconv.Itoa(day) |
|
|
|
} |
|
|
|
|
|
|
|
// 生成顺序码 |
|
|
|
func GeneratorOrderCode(sex int) string { |
|
|
|
rand.Seed(time.Now().Unix()) |
|
|
|
orderCode := rand.Intn(999-111) + 111 |
|
|
|
if sex != orderCode%2 { |
|
|
|
orderCode -= 1 |
|
|
|
} |
|
|
|
|
|
|
|
return strconv.Itoa(orderCode) |
|
|
|
} |
|
|
|
|
|
|
|
// 日期补全 |
|
|
|
func DatePad(date string, category string) string { |
|
|
|
padLength := 2 |
|
|
|
if category == "year" { |
|
|
|
padLength = 4 |
|
|
|
} |
|
|
|
|
|
|
|
return fmt.Sprintf("%s%032s", date, "")[:padLength] |
|
|
|
} |