|
|
package regx
|
|
|
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
"git.sre.ink/go/gtool/date"
|
|
|
"io/ioutil"
|
|
|
"regexp"
|
|
|
"strconv"
|
|
|
)
|
|
|
|
|
|
// Check Perform global verification
|
|
|
func (rr *Regx) IsIdCardCheck(id string) (bool, error) {
|
|
|
//digit check
|
|
|
flag, err := rr.IsValidIdCard(id)
|
|
|
if err != nil {
|
|
|
return flag, err
|
|
|
}
|
|
|
//Check the date
|
|
|
birth := id[6:14]
|
|
|
_, err = rr.CheckBirthdayCode(birth)
|
|
|
if err != nil {
|
|
|
return false, err
|
|
|
}
|
|
|
return true, nil
|
|
|
}
|
|
|
|
|
|
var area = make(map[string]string)
|
|
|
|
|
|
// initConfig locale configuration
|
|
|
func (rr *Regx) initConfig() {
|
|
|
c := "./area.json"
|
|
|
raw, err := ioutil.ReadFile(c)
|
|
|
err = json.Unmarshal(raw, &area)
|
|
|
if err != nil {
|
|
|
err = fmt.Errorf("Failed to parse basic configuration file:%s\n", err.Error())
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// GetProvinceByIdCard get province
|
|
|
func (rr *Regx) GetProvinceByIdCard(address string) string {
|
|
|
rr.initConfig()
|
|
|
address = address[:6]
|
|
|
provincialCode := address[:3] + "000"
|
|
|
cityCode := address[:4] + "00"
|
|
|
return area[provincialCode] + area[cityCode] + area[address]
|
|
|
}
|
|
|
|
|
|
// IsValidCard Verify that the ID is legal
|
|
|
func (rr *Regx) IsValidIdCard(id string) (bool, error) {
|
|
|
if len(id) != 15 && len(id) != 18 {
|
|
|
return false, errors.New("身份证长度不对")
|
|
|
}
|
|
|
return rr.CheckValidNo18(id)
|
|
|
}
|
|
|
|
|
|
// 18-digit ID verification code
|
|
|
func (rr *Regx) CheckValidNo18(id string) (bool, error) {
|
|
|
//string -> []byte
|
|
|
id18 := []byte(id)
|
|
|
nSum := 0
|
|
|
for i := 0; i < len(id18)-1; i++ {
|
|
|
n, _ := strconv.Atoi(string(id18[i]))
|
|
|
nSum += n * weight[i]
|
|
|
}
|
|
|
//mod gets 18-bit ID verification code
|
|
|
mod := nSum % 11
|
|
|
if validValue[mod] == id18[17] {
|
|
|
return true, nil
|
|
|
}
|
|
|
|
|
|
return false, errors.New("身份证不正确请进行核实")
|
|
|
}
|
|
|
|
|
|
// 校验身份证号格式
|
|
|
func (rr *Regx) IsIdCardFormat(identityCard string) bool {
|
|
|
switch len(identityCard) {
|
|
|
case 15:
|
|
|
// 15位身份证号码:15位全是数字
|
|
|
result, _ := regexp.MatchString(`^(\d{15})$`, identityCard)
|
|
|
return result
|
|
|
case 18:
|
|
|
// 18位身份证:前17位为数字,第18位为校验位,可能是数字或X
|
|
|
result, _ := regexp.MatchString(`^(\d{17})([0-9]|X|x)$`, identityCard)
|
|
|
return result
|
|
|
default:
|
|
|
//身份证位数应该为:15位 与 18位
|
|
|
return false
|
|
|
}
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
// GetAgeByIdCard Get age based on ID
|
|
|
func (rr *Regx) GetAgeByIdCard(id string) int {
|
|
|
d := new(date.DateTime)
|
|
|
now := d.Now().Time()
|
|
|
birth, _ := rr.GetBirthByIdCard(id)
|
|
|
startTime, err := d.Parse(birth)
|
|
|
if err != nil {
|
|
|
return 0
|
|
|
}
|
|
|
if startTime.Time().Before(now) {
|
|
|
diff := now.Unix() - startTime.Time().Unix()
|
|
|
Age := diff / (3600 * 365 * 24)
|
|
|
return int(Age)
|
|
|
}
|
|
|
return 0
|
|
|
}
|
|
|
|
|
|
// GetBirthByIdCard get birthday
|
|
|
func (rr *Regx) GetBirthByIdCard(id string) (string, error) {
|
|
|
birth := id[6:14]
|
|
|
_, err := rr.CheckBirthdayCode(birth)
|
|
|
if err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
return birth[:4] + "-" + birth[4:6] + "-" + birth[6:], nil
|
|
|
}
|
|
|
|
|
|
// GetYearByIdCard Year based on ID
|
|
|
func (rr *Regx) GetYearByIdCard(id string) string {
|
|
|
return id[6:14][:4]
|
|
|
}
|
|
|
|
|
|
// GetMonthByIdCard Get the month of your birthday based on your ID
|
|
|
func (rr *Regx) GetMonthByIdCard(id string) string {
|
|
|
return id[6:14][4:6]
|
|
|
}
|
|
|
|
|
|
// GetDayByIdCard Get birthday based on ID
|
|
|
func (rr *Regx) GetDayByIdCard(id string) string {
|
|
|
return id[6:14][6:]
|
|
|
}
|
|
|
|
|
|
// GetSex Get gender based on ID
|
|
|
// Description 0 Female 1 Male 3 unknown ID card gender identification error
|
|
|
func (rr *Regx) GetSex(id string) uint {
|
|
|
var unknown uint = 3
|
|
|
sexStr := id[16:17]
|
|
|
if sexStr == "" {
|
|
|
return unknown
|
|
|
}
|
|
|
i, err := strconv.Atoi(sexStr)
|
|
|
if err != nil {
|
|
|
return unknown
|
|
|
}
|
|
|
if i%2 != 0 {
|
|
|
return 1
|
|
|
}
|
|
|
return 0
|
|
|
}
|
|
|
|
|
|
// Convert15To18 15-digit ID card to 18-digit
|
|
|
// 15位身份证转为18位
|
|
|
var weight = [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
|
|
|
var validValue = [11]byte{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}
|
|
|
|
|
|
func (rr *Regx) Convert15To18(id string) string {
|
|
|
nLen := len(id)
|
|
|
if nLen != 15 {
|
|
|
return "身份证不是15位!"
|
|
|
}
|
|
|
id18 := make([]byte, 0)
|
|
|
id18 = append(id18, id[:6]...)
|
|
|
id18 = append(id18, '1', '9')
|
|
|
id18 = append(id18, id[6:]...)
|
|
|
|
|
|
sum := 0
|
|
|
for i, v := range id18 {
|
|
|
n, _ := strconv.Atoi(string(v))
|
|
|
sum += n * weight[i]
|
|
|
}
|
|
|
mod := sum % 11
|
|
|
id18 = append(id18, validValue[mod])
|
|
|
return string(id18)
|
|
|
}
|