美文网首页
iOS身份证判断正则加算法

iOS身份证判断正则加算法

作者: 蒋大为 | 来源:发表于2018-12-13 10:43 被阅读164次

    身份证常识

    我国的身份证号分为15位和18位两种。身份证是国民的身份编号,编号是有一定规律的。
    居民身份证号码,根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 居民身份证是国家法定的证明公民个人身份的有效证件。

    结构和形式

    1、号码的结构

    公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

    2、地址码

    表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。

    3、出生日期码

    表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。

    4、顺序码

    表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。

    5、校验码

    根据前面十七位数字码,按照ISO7064:1983.MOD11-2校验码计算出来的检验码。

    6、地址码

    华北地区: 北京市|110000,天津市|120000,河北省|130000,山西省|140000,内蒙古自治区|150000,
    东北地区: 辽宁省|210000,吉林省|220000,黑龙江省|230000,
    华东地区: 上海市|310000,江苏省|320000,浙江省|330000,安徽省|340000,福建省|350000,江西省|360000,山东省|370000,
    华中地区: 河南省|410000,湖北省|420000,湖南省|430000
    华南地区: 广东省|440000,广西壮族自治区|450000,海南省|460000,
    西南地区: 重庆市|500000,四川省|510000,贵州省|520000,云南省|530000,西藏自治区|540000,
    西北地区: 陕西省|610000,甘肃省|620000,青海省|630000,宁夏回族自治区|640000,新疆维吾尔自治区|650000,
    特别地区:台湾地区(886)|710000,香港特别行政区(852)|810000,澳门特别行政区(853)|820000
       
    中国大陆居民身份证号码中的地址码的数字编码规则为:
    第一、二位表示省(自治区、直辖市、特别行政区)。

    第三、四位表示市(地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码)。其中,01-20,51-70表示省直辖市;21-50表示地区(自治州、盟)。

    第五、六位表示县(市辖区、县级市、旗)。01-18表示市辖区或地区(自治州、盟)辖县级市;21-80表示县(旗);81-99表示省直辖县级市。

    7、生日期码

    身份证号码第七位到第十四位)表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。

    8、顺序码

    身份证号码第十五位到十七位)地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性

    9、校验码

    作为尾号的校验码,是由号码编制单位按统一的公式计算出来的,如果某人的尾号是0-9,都不会出现X,但如果尾号是10,那么就得用X来代替,因为如果用10做尾号,那么此人的身份证就变成了19位,而19位的号码违反了国家标准,并且中国的计算机应用系统也不承认19位的身份证号码。Ⅹ是罗马数字的10,用X来代替10,可以保证公民的身份证符合国家标准。

    10、身份证校验码的计算方法

    1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
    2、将这17位数字和系数相乘的结果相加。
    3、用加出来和除以11,看余数是多少?
    4、余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X-9-8-7-6-5-4-3-2。(即余数0对应1,余数1对应0,余数2对应X...)
    5、通过上面得知如果余数是3,就会在身份证的第18位数字上出现的是9。如果对应的数字是2,身份证的最后一位号码就是罗马数字x。

    下面直接粘贴代码

    #pragma mark - 检查身份证是否正确
    + (BOOL)checkUserIDCard:(NSString *)value {
        value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        NSInteger length = 0;
        if (!value) {
            return NO;
        } else {
            length = value.length;
            //不满足15位和18位,即身份证错误
            if (length != 15 && length != 18) {
                return NO;
            }
        }
        // 省份代码
        NSArray *areasArray = @[@"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", @"82", @"91"];
        // 检测省份身份行政区代码
        NSString *valueStart2 = [value substringToIndex:2];
        BOOL areaFlag = NO; //标识省份代码是否正确
        for (NSString *areaCode in areasArray) {
            if ([areaCode isEqualToString:valueStart2]) {
                areaFlag = YES;
                break;
            }
        }
    
        if (!areaFlag) {
            return NO;
        }
        
        NSRegularExpression *regularExpression;
        NSUInteger numberofMatch;
    
        int year = 0;
        //分为15位、18位身份证进行校验
        switch (length) {
            case 15:
                //获取年份对应的数字
                year = [value substringWithRange:NSMakeRange(6, 2)].intValue + 1900;
                if (year %4 == 0 || (year %100 == 0 && year %4 == 0)) {
                    //创建正则表达式 NSRegularExpressionCaseInsensitive:不区分字母大小写的模式
                    //测试出生日期的合法性
                    regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$" options:NSRegularExpressionCaseInsensitive error:nil];
                } else {
                    //测试出生日期的合法性
                    regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$"options:NSRegularExpressionCaseInsensitive error:nil];
                }
                //使用正则表达式匹配字符串 NSMatchingReportProgress:找到最长的匹配字符串后调用block回调
                numberofMatch = [regularExpression numberOfMatchesInString:value options:NSMatchingReportProgress range:NSMakeRange(0, value.length)];
                if (numberofMatch > 0) {
                    return YES;
                } else {
                    return NO;
                }
            case 18:
                year = [value substringWithRange:NSMakeRange(6, 4)].intValue;
                if (year %4 == 0 || (year %100 == 0 && year %4 == 0)) {
                    //测试出生日期的合法性
                    regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|71|(8[12])|91)\\d{4}(((19|20)\\d{2}(0[13-9]|1[012])(0[1-9]|[12]\\d|30))|((19|20)\\d{2}(0[13578]|1[02])31)|((19|20)\\d{2}02(0[1-9]|1\\d|2[0-8]))|((19|20)([13579][26]|[2468][048]|0[048])0229))\\d{3}(\\d|X|x)?$" options:NSRegularExpressionCaseInsensitive error:nil];
                } else {
                    //测试出生日期的合法性
                    regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|71|(8[12])|91)\\d{4}(((19|20)\\d{2}(0[13-9]|1[012])(0[1-9]|[12]\\d|30))|((19|20)\\d{2}(0[13578]|1[02])31)|((19|20)\\d{2}02(0[1-9]|1\\d|2[0-8]))|((19|20)([13579][26]|[2468][048]|0[048])0229))\\d{3}(\\d|X|x)?$" options:NSRegularExpressionCaseInsensitive error:nil];
                }
                numberofMatch = [regularExpression numberOfMatchesInString:value options:NSMatchingReportProgress range:NSMakeRange(0, value.length)];
                
                if (numberofMatch > 0) {
                    //1:校验码的计算方法 身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。将这17位数字和系数相乘的结果相加。
                    int S = [value substringWithRange:NSMakeRange(0, 1)].intValue * 7 + [value substringWithRange:NSMakeRange(10, 1)].intValue * 7 + [value substringWithRange:NSMakeRange(1, 1)].intValue * 9 + [value substringWithRange:NSMakeRange(11, 1)].intValue * 9 + [value substringWithRange:NSMakeRange(2, 1)].intValue * 10 + [value substringWithRange:NSMakeRange(12, 1)].intValue * 10 + [value substringWithRange:NSMakeRange(3, 1)].intValue * 5 + [value substringWithRange:NSMakeRange(13, 1)].intValue * 5 + [value substringWithRange:NSMakeRange(4, 1)].intValue * 8 + [value substringWithRange:NSMakeRange(14, 1)].intValue * 8 + [value substringWithRange:NSMakeRange(5, 1)].intValue * 4 + [value substringWithRange:NSMakeRange(15,1)].intValue * 4 + [value substringWithRange:NSMakeRange(6, 1)].intValue * 2 + [value substringWithRange:NSMakeRange(16, 1)].intValue * 2 + [value substringWithRange:NSMakeRange(7, 1)].intValue * 1 + [value substringWithRange:NSMakeRange(8, 1)].intValue * 6 + [value substringWithRange:NSMakeRange(9, 1)].intValue * 3;
                    //2:用加出来和除以11,看余数是多少?余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字
                    int Y = S %11;
                    NSString *M = @"F";
                    NSString *JYM = @"10X98765432";
                    //3:获取校验位
                    M = [JYM substringWithRange:NSMakeRange(Y, 1)];
                    NSString *lastStr = [value substringWithRange:NSMakeRange(17, 1)];
                    CMLog(@"%@",M);
                    CMLog(@"%@",[value substringWithRange:NSMakeRange(17, 1)]);
                    //4:检测ID的校验位
                    if ([lastStr isEqualToString:@"x"]) {
                        if ([M isEqualToString:@"X"]) {
                            return YES;
                        } else {
                            return NO;
                        }
                    } else {
                        if ([M isEqualToString:[value substringWithRange:NSMakeRange(17, 1)]]) {
                            return YES;
                        } else {
                            return NO;
                        }
                    }
                } else {
                    return NO;
                }
            default:
                return NO;
        }
    }
    

    链接:https://www.jianshu.com/p/33ed0d7cb413

    相关文章

      网友评论

          本文标题:iOS身份证判断正则加算法

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