2021-01-11 17:55:24 +08:00
|
|
|
package idvalidator
|
2021-01-10 19:22:33 +08:00
|
|
|
|
|
|
|
import (
|
2021-01-12 11:36:44 +08:00
|
|
|
"github.com/guanguans/id-validator/data"
|
2021-01-10 19:22:33 +08:00
|
|
|
"math"
|
|
|
|
"math/rand"
|
|
|
|
"regexp"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2021-01-11 17:55:24 +08:00
|
|
|
// 生成Bit码
|
2021-01-10 19:22:33 +08:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2021-01-11 17:55:24 +08:00
|
|
|
// 累身份证号body部分与位置加权的积
|
|
|
|
var bodySum int
|
2021-01-10 19:22:33 +08:00
|
|
|
bodyArray := strings.Split(body, "")
|
|
|
|
count := len(bodyArray)
|
|
|
|
for i := 0; i < count; i++ {
|
2021-01-11 17:55:24 +08:00
|
|
|
bodySub, _ := strconv.Atoi(bodyArray[i])
|
|
|
|
bodySum += bodySub * int(posWeight[18-i])
|
2021-01-10 19:22:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 生成校验码
|
|
|
|
checkBit := (12 - (bodySum % 11)) % 11
|
|
|
|
if checkBit == 10 {
|
|
|
|
return "X"
|
|
|
|
}
|
|
|
|
return strconv.Itoa(checkBit)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 生成地址码
|
|
|
|
func GeneratorAddressCode(address string) string {
|
2021-01-11 17:55:24 +08:00
|
|
|
addressCode := ""
|
2021-01-10 19:22:33 +08:00
|
|
|
for code, addressStr := range data.AddressCode {
|
|
|
|
if address == addressStr {
|
2021-01-11 17:55:24 +08:00
|
|
|
addressCode = strconv.Itoa(code)
|
2021-01-10 19:22:33 +08:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-11 17:55:24 +08:00
|
|
|
classification := AddressCodeClassification(addressCode)
|
2021-01-10 19:22:33 +08:00
|
|
|
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
|
2021-01-11 11:53:22 +08:00
|
|
|
for key := range data.AddressCode {
|
2021-01-10 19:22:33 +08:00
|
|
|
keyStr := strconv.Itoa(key)
|
|
|
|
if mustCompile.MatchString(keyStr) && Substr(keyStr, 4, 6) != "00" {
|
|
|
|
keys = append(keys, keyStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rand.Seed(time.Now().Unix())
|
|
|
|
|
2021-01-11 17:55:24 +08:00
|
|
|
return keys[rand.Intn(len(keys))]
|
2021-01-10 19:22:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 生成出生日期码
|
|
|
|
func GeneratorBirthdayCode(birthday string) string {
|
2021-01-11 17:55:24 +08:00
|
|
|
year := DatePipelineHandle(DatePad(Substr(birthday, 0, 4), "year"), "year")
|
|
|
|
month := DatePipelineHandle(DatePad(Substr(birthday, 4, 6), "month"), "month")
|
|
|
|
day := DatePipelineHandle(DatePad(Substr(birthday, 6, 8), "day"), "day")
|
2021-01-10 19:22:33 +08:00
|
|
|
|
2021-01-11 17:55:24 +08:00
|
|
|
birthday = year + month + day
|
|
|
|
_, error := time.Parse("20060102", birthday)
|
|
|
|
// example: 195578
|
|
|
|
if error != nil {
|
|
|
|
year = DatePad(year, "year")
|
|
|
|
month = DatePad(month, "month")
|
|
|
|
day = DatePad(day, "day")
|
2021-01-10 19:22:33 +08:00
|
|
|
}
|
|
|
|
|
2021-01-11 17:55:24 +08:00
|
|
|
return year + month + day
|
|
|
|
}
|
2021-01-10 19:22:33 +08:00
|
|
|
|
2021-01-11 17:55:24 +08:00
|
|
|
// 日期处理
|
|
|
|
func DatePipelineHandle(date string, category string) string {
|
|
|
|
dateInt, _ := strconv.Atoi(date)
|
|
|
|
|
|
|
|
switch category {
|
|
|
|
case "year":
|
|
|
|
nowYear := time.Now().Year()
|
|
|
|
rand.Seed(time.Now().Unix())
|
|
|
|
if dateInt < 1800 || dateInt > nowYear {
|
|
|
|
randDate := rand.Intn(nowYear-1950) + 1950
|
|
|
|
date = strconv.Itoa(randDate)
|
|
|
|
}
|
|
|
|
case "month":
|
|
|
|
if dateInt < 1 || dateInt > 12 {
|
|
|
|
randDate := rand.Intn(12-1) + 1
|
|
|
|
date = strconv.Itoa(randDate)
|
|
|
|
}
|
2021-01-10 19:22:33 +08:00
|
|
|
|
2021-01-11 17:55:24 +08:00
|
|
|
case "day":
|
|
|
|
if dateInt < 1 || dateInt > 31 {
|
|
|
|
randDate := rand.Intn(28-1) + 1
|
|
|
|
date = strconv.Itoa(randDate)
|
|
|
|
}
|
2021-01-10 19:22:33 +08:00
|
|
|
}
|
|
|
|
|
2021-01-11 17:55:24 +08:00
|
|
|
return date
|
2021-01-10 19:22:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 生成顺序码
|
|
|
|
func GeneratorOrderCode(sex int) string {
|
|
|
|
rand.Seed(time.Now().Unix())
|
|
|
|
orderCode := rand.Intn(999-111) + 111
|
|
|
|
if sex != orderCode%2 {
|
2021-01-11 17:55:24 +08:00
|
|
|
orderCode--
|
2021-01-10 19:22:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return strconv.Itoa(orderCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 日期补全
|
|
|
|
func DatePad(date string, category string) string {
|
|
|
|
padLength := 2
|
|
|
|
if category == "year" {
|
|
|
|
padLength = 4
|
|
|
|
}
|
|
|
|
|
2021-01-11 11:53:22 +08:00
|
|
|
for i := 0; i < padLength; i++ {
|
|
|
|
length := len([]rune(date))
|
|
|
|
if length < padLength {
|
|
|
|
// date = fmt.Sprintf("%s%s", "0", date)
|
|
|
|
date = "0" + date
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return date
|
2021-01-10 19:22:33 +08:00
|
|
|
}
|