iOS - 身份证判断正则加算法
身份证常识
我国的身份证号分为15位和18位两种。身份证是国民的身份编号,编号是有一定规律的。
居民身份证号码,根据〖中华人民共和国国家标准 GB -〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 居民身份证是国家法定的证明公民个人身份的有效证件。
结构和形式
1.号码的结构
公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
2.地址码
表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。
3.出生日期码
表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。
4.顺序码
表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
5.校验码
根据前面十七位数字码,按照ISO7064:.MOD11-2校验码计算出来的检验码。
6.地址码
华北地区: 北京市|,天津市|,河北省|,山西省|,内蒙古自治区|,
东北地区: 辽宁省|,吉林省|,黑龙江省|,
华东地区: 上海市|,江苏省|,浙江省|,安徽省|,福建省|,江西省|,山东省|,
华中地区: 河南省|,湖北省|,湖南省|
华南地区: 广东省|,广西壮族自治区|,海南省|,
西南地区: 重庆市|,四川省|,贵州省|,云南省|,西藏自治区|,
西北地区: 陕西省|,甘肃省|,青海省|,宁夏回族自治区|,新疆维吾尔自治区|,
特别地区:台湾地区()|,香港特别行政区()|,澳门特别行政区()|
中国大陆居民身份证号码中的地址码的数字编码规则为:
第一、二位表示省(自治区、直辖市、特别行政区)。
第三、四位表示市(地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码)。其中,-,-70表示省直辖市;-50表示地区(自治州、盟)。
第五、六位表示县(市辖区、县级市、旗)。-18表示市辖区或地区(自治州、盟)辖县级市;-80表示县(旗);-99表示省直辖县级市。
7.生日期码
身份证号码第七位到第十四位)表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。
8.顺序码
身份证号码第十五位到十七位)地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性
9.校验码
作为尾号的校验码,是由号码编制单位按统一的公式计算出来的,如果某人的尾号是0-,都不会出现X,但如果尾号是10,那么就得用X来代替,因为如果用10做尾号,那么此人的身份证就变成了19位,而19位的号码违反了国家标准,并且中国的计算机应用系统也不承认19位的身份证号码。Ⅹ是罗马数字的10,用X来代替10,可以保证公民的身份证符合国家标准。
10.身份证校验码的计算方法
、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:----------------。
、将这17位数字和系数相乘的结果相加。
、用加出来和除以11,看余数是多少?
、余数只可能有0----------10这11个数字。其分别对应的最后一位身份证的号码为1--X--------。(即余数0对应1,余数1对应0,余数2对应X...)
、通过上面得知如果余数是3,就会在身份证的第18位数字上出现的是9。如果对应的数字是2,身份证的最后一位号码就是罗马数字x。
下面直接粘贴代码
OC版本的
+(BOOL)validateIDCardNumber:(NSString *)value {
     value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
     NSInteger length =;
     if (!value) {
         return NO;
         }else {
             length = value.length;
             //不满足15位和18位,即身份证错误
             if (length != && length !=) {
                 return NO;
                 }
             }
     // 省份代码
     NSArray *areasArray = @[@"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @"",@"", @""];
     // 检测省份身份行政区代码
     NSString *valueStart2 = [value substringToIndex:];
     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 =;
     //分为15位、18位身份证进行校验
     switch (length) {
             case :
             //获取年份对应的数字
             year = [value substringWithRange:NSMakeRange(,)].intValue +;
             if (year % == || (year % == && year % ==)) {
                 //创建正则表达式 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(, value.length)];
             if(numberofMatch >) {
                 return YES;
                 }else {
                     return NO;
                     }
             case :
             year = [value substringWithRange:NSMakeRange(,)].intValue;
             if (year % == || (year % == && year % ==)) {
                 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(, value.length)];
             if(numberofMatch >) {
                 //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(,)].intValue* + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue* + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue* + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue* + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue* + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue* + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue* + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue * + [value substringWithRange:NSMakeRange(,)].intValue *;
                 //2:用加出来和除以11,看余数是多少?余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字
                 int Y = S %;
                 NSString *M =@"F";
                 NSString *JYM =@"10X98765432";
                 M = [JYM substringWithRange:NSMakeRange(Y,)];// 3:获取校验位
                 NSString *lastStr = [value substringWithRange:NSMakeRange(,)];
                 NSLog(@"%@",M);
                 NSLog(@"%@",[value substringWithRange:NSMakeRange(,)]);
                 //4:检测ID的校验位
                 if ([lastStr isEqualToString:@"x"]) {
                     if ([M isEqualToString:@"X"]) {
                         return YES;
                         }else{
                             return NO;
                             }
                     }else{
                         if ([M isEqualToString:[value substringWithRange:NSMakeRange(,)]]) {
                             return YES;
                             }else {
                                 return NO;
                                 }
                         }
                 }else {
                     return NO;
                     }
             default:
             return NO;
         }
     }
Swift版本的
func isTrueIDNumber(text:String) -> Bool{
    var value = text
    value = value.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    var length : Int = 
    length = value.characters.count
    if length !=  && length != {
        //不满足15位和18位,即身份证错误
        return false
    }
    // 省份代码
    let areasArray = ["","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", ""]
    // 检测省份身份行政区代码
    let index = value.index(value.startIndex, offsetBy: )
    let valueStart2 = value.substring(to: index)
    //标识省份代码是否正确
    var areaFlag = false
    for areaCode in areasArray {
        if areaCode == valueStart2 {
            areaFlag = true
            break
        }
    }
    if !areaFlag {
        return false
    }
    var regularExpression : NSRegularExpression?
    var numberofMatch : Int?
    var year = 
    switch length {
    case :
        //获取年份对应的数字
        let valueNSStr = value as NSString
        let yearStr = valueNSStr.substring(with: NSRange.init(location: , length: )) as NSString
        year = yearStr.integerValue + 
        if year %  ==  || (year %  ==  && year %  == ) {
            //创建正则表达式 NSRegularExpressionCaseInsensitive:不区分字母大小写的模式
            //测试出生日期的合法性
            regularExpression = try! NSRegularExpression.init(pattern: "^[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: NSRegularExpression.Options.caseInsensitive)
        }else{
            //测试出生日期的合法性
            regularExpression = try! NSRegularExpression.init(pattern: "^[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: NSRegularExpression.Options.caseInsensitive)
        }
        numberofMatch = regularExpression?.numberOfMatches(in: value, options: NSRegularExpression.MatchingOptions.reportProgress, range: NSRange.init(location: , length: value.characters.count))
        if numberofMatch! >  {
            return true
        }else{
            return false
        }
    case :
        let valueNSStr = value as NSString
        let yearStr = valueNSStr.substring(with: NSRange.init(location: , length: )) as NSString
        year = yearStr.integerValue
        if year %  ==  || (year %  ==  && year %  == ) {
            //测试出生日期的合法性
            regularExpression = try! NSRegularExpression.init(pattern: "^((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: NSRegularExpression.Options.caseInsensitive)
        }else{
            //测试出生日期的合法性
            regularExpression = try! NSRegularExpression.init(pattern: "^((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: NSRegularExpression.Options.caseInsensitive)
        }
        numberofMatch = regularExpression?.numberOfMatches(in: value, options: NSRegularExpression.MatchingOptions.reportProgress, range: NSRange.init(location: , length: value.characters.count))
        if numberofMatch! >  {
            let a = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let b = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let c = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let d = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let e = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let f = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let g = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let h = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let i = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let j = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let k = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let l = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let m = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let n = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let o = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let p = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let q = getStringByRangeIntValue(Str: valueNSStr, location: , length: ) * 
            let S = a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q
            let Y = S % 
            var M = "F"
            let JYM = "10X98765432"
            M = (JYM as NSString).substring(with: NSRange.init(location: Y, length: ))
            let lastStr = valueNSStr.substring(with: NSRange.init(location: , length: ))
            if lastStr == "x" {
                if M == "X" {
                    return true
                }else{
                    return false
                }
            }else{
                if M == lastStr {
                    return true
                }else{
                    return false
                }
            }
        }else{
            return false
        }
    default:
        return false
    }
}
func getStringByRangeIntValue(Str : NSString,location : Int, length : Int) -> Int{
    let a = Str.substring(with: NSRange(location: location, length: length))
    let intValue = (a as NSString).integerValue
    return intValue
}
iOS - 身份证判断正则加算法的更多相关文章
- iOS身份证的正则验证
		
在ios项目的开发中可能很多地方都需要用到身份证校验,一般在开发的时候很多人都是直接百度去网上荡相关的正则表达式和校验代码,但是网上疯狂粘贴复制的校验代码本身也可能并不准确,可能会有风险,比如2013 ...
 - iOS - UITableView判断reloadData加载数据已经结束
		
问题: stackoverflow上有人提问这样的问题 http://stackoverflow.com/questions/16071503/how-to-tell-when-uitableview ...
 - iOS - 正则表达式判断邮箱、身份证..是否正确:
		
iOS - 正则表达式判断邮箱.身份证..是否正确: //邮箱 + (BOOL) validateEmail:(NSString *)email { NSString *emailRegex ...
 - iOS身份证号码识别
		
一.前言 身份证识别,又称OCR技术.OCR技术是光学字符识别的缩写,是通过扫描等光学输入方式将各种票据.报刊.书籍.文稿及其它印刷品的文字转化为图像信息,再利用文字识别技术将图像信息转化为可以使 ...
 - iOS开发中正则式的使用
		
iOS开发中正则式的使用 第一:常规的使用方式 NSString *str = @"abcded111093212qweqw"; //找到内部一个即可 NSString *patt ...
 - ios客户端浏览器样式加载失效问题
		
最近线上测试中出现一个奇怪的问题,ios客户端浏览器样式加载失效. 从表象来看,同样的css,安卓手机上可以正常展示,但是到ios手机上首次进入页面就不能正常显示 这时候,我们首先会考虑是不是ios设 ...
 - IOS的变量前加extern和static字段
		
IOS的变量前加extern和static字段 前一阵子,做项目的时候到网上找Demo,打开运行的时候发现其中变量前有关键字extern和static,所以我研究了一下子 对于extern来说可以理解 ...
 - IOS 多个UIImageView 加载高清大图时内存管理
		
IOS 多个UIImageView 加载高清大图时内存管理 时间:2014-08-27 10:47 浏览:59人 当我们在某一个View多个UIImageView,且UIImageView都显示的是 ...
 - ios如何判断键盘是否已经显示
		
ios如何判断键盘是否已经显示 在群里看到有人问:ios如何判断键盘已经显示在界面上. 其实这个解决很简单: 写一个单例来管理键盘的状态. 这个单例在初始化方法init种监听2个事件,分别是 UI ...
 
随机推荐
- 奇怪吸引子---NoseHoover
			
奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...
 - MDX Cookbook 01 - Skipping Axis 合理使用空的 SET 集合获取全部层次结构成员
			
假设我们只想显示一些与数据没有任何关联的维度成员信息,并且希望它们能够以行集的形式来显示,那么在 MDX 中就应该直接显示 ROWS AXIS (1) 并且忽略掉 COLUMNS AXIS(0).比 ...
 - 下载fiddler证书并设置信任
			
一.苹果手机 待整理 二.android手机 待整理
 - 通过jarjar.jar来替换jar包名的详细介绍
			
有时候我们根据一些场景 需要替换第三方jar包的包名,比如Android广告平台sdk,更换他们jar包包名的话,可以防止市场检测到有广告插件,所以,今天就介绍一下如何使用jarjar.jar工具来替 ...
 - EasyUI  tab问题记录
			
1. 关闭当前tab 此代码放在 布局页中,然后所有的页面都可以随时关闭tab了,适当的根据你的项目,更改下js <script> function closetab(subtitle ...
 - js 学习
			
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta chars ...
 - linux 重启和关机
			
重启命令有:reboot, shutdown -ry 0关机命令有:poweroff, shutdown -hy 0
 - samba需求,请建一个目录,所有用户都可以修改其中的任意文件(新建文件的权限问题)
			
我的配置如下: [TMP] comment = Public Stuff path = /DATA/samba/tmp public = yes writable = yes create mode ...
 - vue的双向绑定
			
1.效果 点击+-修改数量,金额跟着一起变动 2.index.html <!DOCTYPE html> <html lang="en"> <head& ...
 - Java8 中增强 Future:CompletableFuture
			
增强的 Future:CompletableFuture CompletableFuture(它实现了 Future 接口) 和 Future 一样,可以作为函数调用的契约.当你向它请求获得结果,如果 ...