You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

181 lines
4.3 KiB

  1. package id_validator
  2. import (
  3. "id-validator/data"
  4. "math"
  5. "math/rand"
  6. "regexp"
  7. "strconv"
  8. "strings"
  9. "time"
  10. )
  11. // 生成 Bit 码
  12. func GeneratorCheckBit(body string) string {
  13. // 位置加权
  14. var posWeight [19]float64
  15. for i := 2; i < 19; i++ {
  16. weight := int(math.Pow(2, float64(i-1))) % 11
  17. posWeight[i] = float64(weight)
  18. }
  19. // 累身份证号 body 部分与位置加权的积
  20. bodySum := 0
  21. bodyArray := strings.Split(body, "")
  22. count := len(bodyArray)
  23. for i := 0; i < count; i++ {
  24. bodySubStr, _ := strconv.Atoi(bodyArray[i])
  25. bodySum += bodySubStr * int(posWeight[18-i])
  26. }
  27. // 生成校验码
  28. checkBit := (12 - (bodySum % 11)) % 11
  29. if checkBit == 10 {
  30. return "X"
  31. }
  32. return strconv.Itoa(checkBit)
  33. }
  34. // 生成地址码
  35. func GeneratorAddressCode(address string) string {
  36. var addressCodeInt int
  37. for code, addressStr := range data.AddressCode {
  38. if address == addressStr {
  39. addressCodeInt = code
  40. break
  41. }
  42. }
  43. addressCode := strconv.Itoa(addressCodeInt)
  44. classification := AddressCodeClassification(strconv.Itoa(addressCodeInt))
  45. switch classification {
  46. case "country":
  47. // addressCode = GetRandAddressCode("\\d{4}(?!00)[0-9]{2}$")
  48. addressCode = GetRandAddressCode("\\d{4}(?)[0-9]{2}$")
  49. case "province":
  50. provinceCode := Substr(addressCode, 0, 2)
  51. // pattern := "^" + provinceCode + "\\d{2}(?!00)[0-9]{2}$"
  52. pattern := "^" + provinceCode + "\\d{2}(?)[0-9]{2}$"
  53. addressCode = GetRandAddressCode(pattern)
  54. case "city":
  55. cityCode := Substr(addressCode, 0, 4)
  56. // pattern := "^" + cityCode + "(?!00)[0-9]{2}$"
  57. pattern := "^" + cityCode + "(?)[0-9]{2}$"
  58. addressCode = GetRandAddressCode(pattern)
  59. }
  60. return addressCode
  61. }
  62. // 地址码分类
  63. func AddressCodeClassification(addressCode string) string {
  64. // 全国
  65. if addressCode == "" {
  66. return "country"
  67. }
  68. // 港澳台
  69. if Substr(addressCode, 0, 1) == "8" {
  70. return "special"
  71. }
  72. // 省级
  73. if Substr(addressCode, 2, 6) == "0000" {
  74. return "province"
  75. }
  76. // 市级
  77. if Substr(addressCode, 4, 6) == "00" {
  78. return "city"
  79. }
  80. // 县级
  81. return "district"
  82. }
  83. // 获取随机地址码
  84. func GetRandAddressCode(pattern string) string {
  85. mustCompile := regexp.MustCompile(pattern)
  86. var keys []string
  87. for key := range data.AddressCode {
  88. keyStr := strconv.Itoa(key)
  89. if mustCompile.MatchString(keyStr) && Substr(keyStr, 4, 6) != "00" {
  90. keys = append(keys, keyStr)
  91. }
  92. }
  93. // initialize global pseudo random generator
  94. rand.Seed(time.Now().Unix())
  95. randKey := rand.Intn(len(keys))
  96. return keys[randKey]
  97. }
  98. // 生成出生日期码
  99. func GeneratorBirthdayCode(birthday string) string {
  100. year, _ := strconv.Atoi(DatePad(Substr(birthday, 0, 4), "year"))
  101. month, _ := strconv.Atoi(DatePad(Substr(birthday, 4, 6), "month"))
  102. day, _ := strconv.Atoi(DatePad(Substr(birthday, 6, 8), "day"))
  103. nowYear := time.Now().Year()
  104. rand.Seed(time.Now().Unix())
  105. if year < 1800 || year > nowYear {
  106. randYear := rand.Intn(nowYear-1950) + 1950
  107. year, _ = strconv.Atoi(DatePad(strconv.Itoa(randYear), "year"))
  108. }
  109. if month < 1 || month > 12 {
  110. randMonth := rand.Intn(12-1) + 1
  111. month, _ = strconv.Atoi(DatePad(strconv.Itoa(randMonth), "month"))
  112. }
  113. if day < 1 || day > 31 {
  114. randDay := rand.Intn(28-1) + 1
  115. day, _ = strconv.Atoi(DatePad(strconv.Itoa(randDay), "day"))
  116. }
  117. birthdayStr := DatePad(strconv.Itoa(year), "year") + DatePad(strconv.Itoa(month), "month") + DatePad(strconv.Itoa(day), "day")
  118. _, error := time.Parse("20060102", birthdayStr)
  119. if error != nil {
  120. randYear := rand.Intn(nowYear-1950) + 1950
  121. year, _ = strconv.Atoi(DatePad(strconv.Itoa(randYear), "year"))
  122. randMonth := rand.Intn(12-1) + 1
  123. month, _ = strconv.Atoi(DatePad(strconv.Itoa(randMonth), "month"))
  124. randDay := rand.Intn(28-1) + 1
  125. day, _ = strconv.Atoi(DatePad(strconv.Itoa(randDay), "day"))
  126. }
  127. return DatePad(strconv.Itoa(year), "year") + DatePad(strconv.Itoa(month), "month") + DatePad(strconv.Itoa(day), "day")
  128. }
  129. // 生成顺序码
  130. func GeneratorOrderCode(sex int) string {
  131. rand.Seed(time.Now().Unix())
  132. orderCode := rand.Intn(999-111) + 111
  133. if sex != orderCode%2 {
  134. orderCode -= 1
  135. }
  136. return strconv.Itoa(orderCode)
  137. }
  138. // 日期补全
  139. func DatePad(date string, category string) string {
  140. padLength := 2
  141. if category == "year" {
  142. padLength = 4
  143. }
  144. for i := 0; i < padLength; i++ {
  145. length := len([]rune(date))
  146. if length < padLength {
  147. // date = fmt.Sprintf("%s%s", "0", date)
  148. date = "0" + date
  149. }
  150. }
  151. return date
  152. }