citizen.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package public
  2. import (
  3. "errors"
  4. "strconv"
  5. "time"
  6. )
  7. var weight = [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
  8. var valid_value = [11]byte{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}
  9. var valid_province = []string{
  10. "11", // 北京市
  11. "12", // 天津市
  12. "13", // 河北省
  13. "14", // 山西省
  14. "15", // 内蒙古自治区
  15. "21", // 辽宁省
  16. "22", // 吉林省
  17. "23", // 黑龙江省
  18. "31", // 上海市
  19. "32", // 江苏省
  20. "33", // 浙江省
  21. "34", // 安徽省
  22. "35", // 福建省
  23. "36", // 山西省
  24. "37", // 山东省
  25. "41", // 河南省
  26. "42", // 湖北省
  27. "43", // 湖南省
  28. "44", // 广东省
  29. "45", // 广西壮族自治区
  30. "46", // 海南省
  31. "50", // 重庆市
  32. "51", // 四川省
  33. "52", // 贵州省
  34. "53", // 云南省
  35. "54", // 西藏自治区
  36. "61", // 陕西省
  37. "62", // 甘肃省
  38. "63", // 青海省
  39. "64", // 宁夏回族自治区
  40. "65", // 新疆维吾尔自治区
  41. "71", // 台湾省
  42. "81", // 香港特别行政区
  43. "91", // 澳门特别行政区
  44. }
  45. // Check citizen number 18 valid.
  46. func IsValidCitizenNo18(citizenNo18 *[]byte) bool {
  47. nLen := len(*citizenNo18)
  48. if nLen != 18 {
  49. return false
  50. }
  51. nSum := 0
  52. for i := 0; i < nLen-1; i++ {
  53. n, _ := strconv.Atoi(string((*citizenNo18)[i]))
  54. nSum += n * weight[i]
  55. }
  56. mod := nSum % 11
  57. if valid_value[mod] == (*citizenNo18)[17] {
  58. return true
  59. }
  60. return false
  61. }
  62. // Convert citizen 15 to 18.
  63. func Citizen15To18(citizenNo15 []byte) []byte {
  64. nLen := len(citizenNo15)
  65. if nLen != 15 {
  66. return nil
  67. }
  68. citizenNo18 := make([]byte, 0)
  69. citizenNo18 = append(citizenNo18, citizenNo15[:6]...)
  70. citizenNo18 = append(citizenNo18, '1', '9')
  71. citizenNo18 = append(citizenNo18, citizenNo15[6:]...)
  72. sum := 0
  73. for i, v := range citizenNo18 {
  74. n, _ := strconv.Atoi(string(v))
  75. sum += n * weight[i]
  76. }
  77. mod := sum % 11
  78. citizenNo18 = append(citizenNo18, valid_value[mod])
  79. return citizenNo18
  80. }
  81. func IsLeapYear(nYear int) bool {
  82. if nYear <= 0 {
  83. return false
  84. }
  85. if (nYear%4 == 0 && nYear%100 != 0) || nYear%400 == 0 {
  86. return true
  87. }
  88. return false
  89. }
  90. // Check birthday's year month day valid.
  91. func CheckBirthdayValid(nYear, nMonth, nDay int) bool {
  92. if nYear < 1900 || nMonth <= 0 || nMonth > 12 || nDay <= 0 || nDay > 31 {
  93. return false
  94. }
  95. curYear, curMonth, curDay := time.Now().Date()
  96. if nYear == curYear {
  97. if nMonth > int(curMonth) {
  98. return false
  99. } else if nMonth == int(curMonth) && nDay > curDay {
  100. return false
  101. }
  102. }
  103. if 2 == nMonth {
  104. if IsLeapYear(nYear) && nDay > 29 {
  105. return false
  106. } else if nDay > 28 {
  107. return false
  108. }
  109. } else if 4 == nMonth || 6 == nMonth || 9 == nMonth || 11 == nMonth {
  110. if nDay > 30 {
  111. return false
  112. }
  113. }
  114. return true
  115. }
  116. // Check province code valid.
  117. func CheckProvinceValid(citizenNo []byte) bool {
  118. provinceCode := make([]byte, 0)
  119. provinceCode = append(provinceCode, citizenNo[:2]...)
  120. provinceStr := string(provinceCode)
  121. for _, str := range valid_province {
  122. if provinceStr == str {
  123. return true
  124. }
  125. }
  126. return false
  127. }
  128. // Check citizen number valid.
  129. func IsValidCitizenNo(citizenNo *[]byte) bool {
  130. nLen := len(*citizenNo)
  131. if nLen != 15 && nLen != 18 {
  132. return false
  133. }
  134. for i, v := range *citizenNo {
  135. n, _ := strconv.Atoi(string(v))
  136. if n >= 0 && n <= 9 {
  137. continue
  138. }
  139. if v == 'X' && i == 16 {
  140. continue
  141. }
  142. return false
  143. }
  144. if !CheckProvinceValid(*citizenNo) {
  145. return false
  146. }
  147. if nLen == 15 {
  148. *citizenNo = Citizen15To18(*citizenNo)
  149. if citizenNo == nil {
  150. return false
  151. }
  152. } else if !IsValidCitizenNo18(citizenNo) {
  153. return false
  154. }
  155. nYear, _ := strconv.Atoi(string((*citizenNo)[6:10]))
  156. nMonth, _ := strconv.Atoi(string((*citizenNo)[10:12]))
  157. nDay, _ := strconv.Atoi(string((*citizenNo)[12:14]))
  158. if !CheckBirthdayValid(nYear, nMonth, nDay) {
  159. return false
  160. }
  161. return true
  162. }
  163. // Get information from citizen number. Birthday, gender, province mask.
  164. func GetCitizenNoInfo(citizenNo []byte) (err error, birthday int64, isMale bool, addrMask int) {
  165. err = nil
  166. birthday = 0
  167. isMale = false
  168. addrMask = 0
  169. if !IsValidCitizenNo(&citizenNo) {
  170. err = errors.New("Invalid citizen number.")
  171. return
  172. }
  173. // Birthday information.
  174. nYear, _ := strconv.Atoi(string(citizenNo[6:10]))
  175. nMonth, _ := strconv.Atoi(string(citizenNo[10:12]))
  176. nDay, _ := strconv.Atoi(string(citizenNo[12:14]))
  177. birthday = time.Date(nYear, time.Month(nMonth), nDay, 0, 0, 0, 0, time.Local).Unix()
  178. // Gender information.
  179. genderMask, _ := strconv.Atoi(string(citizenNo[16]))
  180. if genderMask%2 == 0 {
  181. isMale = false
  182. } else {
  183. isMale = true
  184. }
  185. // Address code mask.
  186. addrMask, _ = strconv.Atoi(string(citizenNo[:2]))
  187. return
  188. }