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 ...
随机推荐
- shell自动补全功能:bash和zsh
首要一点:shell有多种,比如bash.zsh.csh.ksh.sh.tcsh等 因此,制作自动补全功能时,要先搞清楚,你使用的是哪种shell,各个shell制作方法是不同的,网上大部分介绍的是关 ...
- Go语言之高级篇beego框架之config、httplib、context
一.httplib 1.配置文件解析 这是一个用来解析文件的库,它的设计思路来自于 database/sql,目前支持解析的文件格式有 ini.json.xml.yaml,可以通过如下方式进行安装: ...
- 如何Python下载大文件?
我想用python脚本下载很多文件,但是经常就有那么几个出错,写了个error handling,跳了过去,但是把出错的链接保存了一下. 转过天来,研究了一下出的什么错. 一个报错如下: PS C:\ ...
- WPF如何为程序添加splashScreen(初始屏幕)
一.考虑到大部分的splashscreen其实都只是一个图片,所以最简单的做法是,先导入一张图片,然后设置它的生成操作为“splash screen” 二.通过程序设置SplashScreen pub ...
- PL/SQL学习笔记之游标
一:游标 Oracle会创建一个上下文区域,用于处理SQL语句,其中包含需要处理的语句.处理结果等等. 游标指向这一上下文的区域. PL/SQL通过控制游标在上下文区域移动,来获取SQL语句的结果信息 ...
- 修改oracle为归档模式
1.查看是否为归档模式 SQL> archive log list; Database log mode No Archive Mode Automatic archival Disabled ...
- JavaScript绑定this
问题描述 var a = { one: 1, haha() { console.log(this.one) } } setTimeout(a.haha, 1000) 在上例中,函数haha引用了thi ...
- [转载]js正则表达式/replace替换变量方法
原文地址:http://www.blogjava.net/pingpang/archive/2012/08/12/385342.html JavaScript正则实战(会根据最近写的不断更新) 1.j ...
- Android 组件系列-----Activity生命周期
本篇随笔将会深入学习Activity,包括如何定义多个Activity,并设置为默认的Activity.如何从一个Activity跳转到另一个Activity,还有就是详细分析Activity的生命周 ...
- Badboy教程
Badboy教程 摘自:Badboy-系列教程-资料整理 2016-11-30 1 界面介绍 2 录制 3 创建suites,tests,steps和Template 4 运行脚本 5 参数化 Add ...