美文网首页
Go验证身份证号

Go验证身份证号

作者: 大地缸 | 来源:发表于2021-02-22 09:33 被阅读0次

    title: "Go验证身份证号"
    date: 2021-02-10T07:54:44+08:00
    draft: true
    tags: ['go']
    author: "dadigang"
    author_cn: "大地缸"
    personal: "http://www.real007.cn"


    关于作者

    http://www.real007.cn/about

    golang 身份证信息处理

    功能简单介绍:针对一串身份证字符串(string)的处理:

    1. 验证身份证的正确性

    2. 提取出生年月日

    3. 提取性别

    4. 把15位的身份证号码转成18位

    5. 验证省份代码正确性

    直接上代码:

    package citizen
    
    import (
        "strconv"
        "errors"
        "time"
    )
    
    var weight = [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
    var valid_value = [11]byte{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}
    var valid_province = []string{
        "11",           // 北京市
        "12",           // 天津市
        "13",           // 河北省
        "14",           // 山西省
        "15",           // 内蒙古自治区
        "21",           // 辽宁省
        "22",           // 吉林省
        "23",           // 黑龙江省
        "31",           // 上海市
        "32",           // 江苏省
        "33",           // 浙江省
        "34",           // 安徽省
        "35",           // 福建省
        "36",           // 山西省
        "37",           // 山东省
        "41",           // 河南省
        "42",           // 湖北省
        "43",           // 湖南省
        "44",           // 广东省
        "45",           // 广西壮族自治区
        "46",           // 海南省
        "50",           // 重庆市
        "51",           // 四川省
        "52",           // 贵州省
        "53",           // 云南省
        "54",           // 西藏自治区
        "61",           // 陕西省
        "62",           // 甘肃省
        "63",           // 青海省
        "64",           // 宁夏回族自治区
        "65",           // 新疆维吾尔自治区
        "71",           // 台湾省
        "81",           // 香港特别行政区
        "91",           // 澳门特别行政区
    }
    
    // Check citizen number 18 valid.
    func IsValidCitizenNo18(citizenNo18 *[]byte) bool {
        nLen := len(*citizenNo18)
        if nLen != 18 {
            return false
        }
    
        nSum := 0
        for i := 0; i < nLen - 1; i++ {
            n, _ := strconv.Atoi(string((*citizenNo18)[i]))
            nSum += n * weight[i]
        }
        mod := nSum % 11
        if valid_value[mod] == (*citizenNo18)[17] {
            return true
        }
    
        return false
    }
    
    // Convert citizen 15 to 18.
    func Citizen15To18(citizenNo15 []byte) []byte {
        nLen := len(citizenNo15)
        if nLen != 15 {
            return nil
        }
    
        citizenNo18 := make([]byte, 0)
        citizenNo18 = append(citizenNo18, citizenNo15[:6]...)
        citizenNo18 = append(citizenNo18, '1', '9');
        citizenNo18 = append(citizenNo18, citizenNo15[6:]...)
    
        sum := 0
        for i, v := range citizenNo18 {
            n, _ := strconv.Atoi(string(v))
            sum += n * weight[i]
        }
        mod := sum % 11
        citizenNo18 = append(citizenNo18, valid_value[mod])
    
        return citizenNo18
    }
    
    func IsLeapYear(nYear int) bool {
        if nYear <= 0 {
            return false
        }
    
        if (nYear % 4 == 0 && nYear % 100 != 0) || nYear % 400 == 0 {
            return true
        }
    
        return false
    }
    
    // Check birthday's year month day valid.
    func CheckBirthdayValid(nYear, nMonth, nDay int) bool {
        if nYear < 1900 || nMonth <= 0 || nMonth > 12 || nDay <= 0 || nDay > 31 {
            return false
        }
    
        curYear, curMonth, curDay := time.Now().Date()
        if nYear == curYear {
            if nMonth > int(curMonth) {
                return false
            } else if nMonth == int(curMonth) && nDay > curDay {
                return false
            }
        }
    
        if 2 == nMonth {
            if IsLeapYear(nYear) && nDay > 29 {
                return false
            } else if nDay > 28 {
                return false
            }
        } else if 4 == nMonth || 6 == nMonth || 9 == nMonth || 11 == nMonth {
            if nDay > 30 {
                return false
            }
        }
    
        return true
    }
    
    // Check province code valid.
    func CheckProvinceValid(citizenNo []byte) bool {
        provinceCode := make([]byte, 0)
        provinceCode = append(provinceCode, citizenNo[:2]...)
        provinceStr := string(provinceCode)
    
        for i, _ := range valid_province {
            if provinceStr == valid_province[i] {
                return true
            }
        }
    
        return false
    }
    
    // Check citizen number valid.
    func IsValidCitizenNo(citizenNo *[]byte) bool {
        nLen := len(*citizenNo)
        if nLen != 15 && nLen != 18 {
            return false
        }
    
        for i, v := range *citizenNo {
            n, _ := strconv.Atoi(string(v))
            if n >= 0 && n <= 9 {
                continue
            }
    
            if v == 'X' && i == 16 {
                continue
            }
    
            return false
        }
    
        if !CheckProvinceValid(*citizenNo) {
            return false
        }
    
        if nLen == 15 {
            *citizenNo = Citizen15To18(*citizenNo)
            if citizenNo == nil {
                return false
            }
        } else if !IsValidCitizenNo18(citizenNo) {
            return false
        }
    
        nYear, _ := strconv.Atoi(string((*citizenNo)[6:10]))
        nMonth, _ := strconv.Atoi(string((*citizenNo)[10:12]))
        nDay, _ := strconv.Atoi(string((*citizenNo)[12:14]))
        if !CheckBirthdayValid(nYear, nMonth, nDay) {
            return false
        }
    
        return true
    }
    
    // Get information from citizen number. Birthday, gender, province mask.
    func GetCitizenNoInfo(citizenNo []byte) (err error, birthday int64, isMale bool, addrMask int) {
        err = nil
        birthday = 0
        isMale = false
        addrMask = 0
        if !IsValidCitizenNo(&citizenNo) {
            err = errors.New("Invalid citizen number.")
            return
        }
    
        // Birthday information.
        nYear, _ := strconv.Atoi(string(citizenNo[6:10]))
        nMonth, _ := strconv.Atoi(string(citizenNo[10:12]))
        nDay, _ := strconv.Atoi(string(citizenNo[12:14]))
        birthday = time.Date(nYear, time.Month(nMonth), nDay, 0, 0, 0, 0, time.Local).Unix()
    
        // Gender information.
        genderMask, _ := strconv.Atoi(string(citizenNo[16]))
        if genderMask % 2 == 0 {
            isMale = false
        } else {
            isMale = true
        }
    
        // Address code mask.
        addrMask, _ = strconv.Atoi(string(citizenNo[:2]))
    
        return
    }
    
    

    测试代码:

    package main
    
    import (
        "fmt"
        "go_code/citizentest/citizen"
    )
    
    func main() {
        // citizenNo := []byte("340321199001234560")
        citizenNo := []byte("340321900123456")
        err, birthday, isMale, addrMask := citizen.GetCitizenNoInfo(citizenNo)
        if err != nil {
            fmt.Println("Invalid citizen number.")
        } else {
                fmt.Println("Valid citizen number.")
                fmt.Printf("Information from citizen: birthday=%v, ismale=%v, addrmask=%d\n", birthday, isMale, addrMask)
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Go验证身份证号

          本文链接:https://www.haomeiwen.com/subject/rdypxltx.html