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.

185 lines
4.0 KiB

  1. package idvalidator
  2. import (
  3. "github.com/guanguans/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. var bodySum int
  21. bodyArray := strings.Split(body, "")
  22. count := len(bodyArray)
  23. for i := 0; i < count; i++ {
  24. bodySub, _ := strconv.Atoi(bodyArray[i])
  25. bodySum += bodySub * 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. addressCode := ""
  37. for code, addressStr := range data.AddressCode {
  38. if address == addressStr {
  39. addressCode = strconv.Itoa(code)
  40. break
  41. }
  42. }
  43. classification := addressCodeClassification(addressCode)
  44. switch classification {
  45. case "country":
  46. // addressCode = getRandAddressCode("\\d{4}(?!00)[0-9]{2}$")
  47. addressCode = getRandAddressCode("\\d{4}(?)[0-9]{2}$")
  48. case "province":
  49. provinceCode := substr(addressCode, 0, 2)
  50. // pattern := "^" + provinceCode + "\\d{2}(?!00)[0-9]{2}$"
  51. pattern := "^" + provinceCode + "\\d{2}(?)[0-9]{2}$"
  52. addressCode = getRandAddressCode(pattern)
  53. case "city":
  54. cityCode := substr(addressCode, 0, 4)
  55. // pattern := "^" + cityCode + "(?!00)[0-9]{2}$"
  56. pattern := "^" + cityCode + "(?)[0-9]{2}$"
  57. addressCode = getRandAddressCode(pattern)
  58. }
  59. return addressCode
  60. }
  61. // 地址码分类
  62. func addressCodeClassification(addressCode string) string {
  63. // 全国
  64. if addressCode == "" {
  65. return "country"
  66. }
  67. // 港澳台
  68. if substr(addressCode, 0, 1) == "8" {
  69. return "special"
  70. }
  71. // 省级
  72. if substr(addressCode, 2, 6) == "0000" {
  73. return "province"
  74. }
  75. // 市级
  76. if substr(addressCode, 4, 6) == "00" {
  77. return "city"
  78. }
  79. // 县级
  80. return "district"
  81. }
  82. // 获取随机地址码
  83. func getRandAddressCode(pattern string) string {
  84. mustCompile := regexp.MustCompile(pattern)
  85. var keys []string
  86. for key := range data.AddressCode {
  87. keyStr := strconv.Itoa(key)
  88. if mustCompile.MatchString(keyStr) && substr(keyStr, 4, 6) != "00" {
  89. keys = append(keys, keyStr)
  90. }
  91. }
  92. rand.Seed(time.Now().Unix())
  93. return keys[rand.Intn(len(keys))]
  94. }
  95. // 生成出生日期码
  96. func generatorBirthdayCode(birthday string) string {
  97. year := datePipelineHandle(datePad(substr(birthday, 0, 4), "year"), "year")
  98. month := datePipelineHandle(datePad(substr(birthday, 4, 6), "month"), "month")
  99. day := datePipelineHandle(datePad(substr(birthday, 6, 8), "day"), "day")
  100. birthday = year + month + day
  101. _, error := time.Parse("20060102", birthday)
  102. // example: 195578
  103. if error != nil {
  104. year = datePad(year, "year")
  105. month = datePad(month, "month")
  106. day = datePad(day, "day")
  107. }
  108. return year + month + day
  109. }
  110. // 日期处理
  111. func datePipelineHandle(date string, category string) string {
  112. dateInt, _ := strconv.Atoi(date)
  113. switch category {
  114. case "year":
  115. nowYear := time.Now().Year()
  116. rand.Seed(time.Now().Unix())
  117. if dateInt < 1800 || dateInt > nowYear {
  118. randDate := rand.Intn(nowYear-1950) + 1950
  119. date = strconv.Itoa(randDate)
  120. }
  121. case "month":
  122. if dateInt < 1 || dateInt > 12 {
  123. randDate := rand.Intn(12-1) + 1
  124. date = strconv.Itoa(randDate)
  125. }
  126. case "day":
  127. if dateInt < 1 || dateInt > 31 {
  128. randDate := rand.Intn(28-1) + 1
  129. date = strconv.Itoa(randDate)
  130. }
  131. }
  132. return date
  133. }
  134. // 生成顺序码
  135. func generatorOrderCode(sex int) string {
  136. rand.Seed(time.Now().Unix())
  137. orderCode := rand.Intn(999-111) + 111
  138. if sex != orderCode%2 {
  139. orderCode--
  140. }
  141. return strconv.Itoa(orderCode)
  142. }
  143. // 日期补全
  144. func datePad(date string, category string) string {
  145. padLength := 2
  146. if category == "year" {
  147. padLength = 4
  148. }
  149. for i := 0; i < padLength; i++ {
  150. length := len([]rune(date))
  151. if length < padLength {
  152. // date = fmt.Sprintf("%s%s", "0", date)
  153. date = "0" + date
  154. }
  155. }
  156. return date
  157. }