選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

generator.go 4.0 KiB

3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. }