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 ...
随机推荐
- RxJava2 源码解析(一)
概述 最近事情太多了,现在公司内部的变动,自己岗位的变化,以及最近决定找工作.所以博客耽误了,准备面试中,打算看一看RxJava2的源码,遂有了这篇文章. 不会对RxJava2的源码逐字逐句的阅读,只 ...
- 1.1 lambda表达式
一.处理匿名内部类 1.Runnable接口 new Thread(new Runnable() { public void run() { System.out.println("hell ...
- C# Round源码
在日常开发中经常遇到四舍五入的情况比如 Math.Round(1.25, 1),首先我们要知道这里的Round 其实是银行家算法,具体可以参考Round() 四舍五入 js银行家算法 那么C#是如何实 ...
- 读懂isi get的结果
你想知道的一切,在这里: Isi Get & Set https://community.emc.com/community/products/isilon/blog/2018/02/21/i ...
- 深入理解Git (一) - 元数据
三分钟教你学Git仅仅是教我们会用Git了,但是内部的一些实现原理假设我们也知道一些的话会使我们使用起来更加顺手.这个系列就是在你用了Git一段时间之后,并想继续到Git的内部看一下到底而准备的. G ...
- Oracle更改redo log大小 or 增加redo log组
(1)redo log的大小可以影响 DBWR 和 checkpoint : (2)arger redo log files provide better performance. Undersize ...
- 【MySQL】MySQL视图创建、查询。
视图是指计算机数据库中的视图,是一个虚拟表.关系型数据库中的数据是由一张一张的二维关系表所组成,简单的单表查询只需要遍历一个表,而复杂的多表查询需要将多个表连接起来进行查询任务.对于复杂的查询事件,每 ...
- system函数遇到的问题
这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以 ...
- windows环境telnet发送命令
telnet *.*.*.* port ,然后crtl+]进入命令模式,使用send发送消息,如:send hello,murphy 常用命令: open : 使用 openhostname 可以建立 ...
- django --- DetailView源码分析
[背景] 最近在看django官方文档的class-based-views这一节的时候一直不得要领,感觉自己清楚,但是回想起来又没有脉络:于是没有办法只 能是“暗中观察”django的源码了. 刚打开 ...