來源于Java同事的文檔和核心邏輯,廢話不多說搔确,直接上代碼
/**
判斷身份證號碼是否符合規(guī)范
@param identityString 身份證號碼
@return 正確bool值
*/
- (BOOL)judgeIdentityStringValid:(NSString *)identityString {
/*
* 身份證號碼驗證
* 1.號碼的結(jié)構(gòu) 公民身份號碼是特征組合碼杆烁,由十七位數(shù)字本體碼和一位校驗碼組成。排列順序從左至右依次為:六位數(shù)字地址碼禽翼,八位數(shù)字出生日期碼屠橄,三位數(shù)字順序碼和一位數(shù)字校驗碼。
* 2.地址碼(前六位數(shù))
* 表示編碼對象常住戶口所在縣(市闰挡、旗锐墙、區(qū))的行政區(qū)劃代碼,按GB/T2260的規(guī)定執(zhí)行长酗。
* 3.出生日期碼(第七位至十四位)
* 表示編碼對象出生的年溪北、月、日夺脾,按GB/T7408的規(guī)定執(zhí)行之拨,年、月咧叭、日代碼之間不用分隔符蚀乔。
* 4.順序碼(第十五位至十七位)
* 表示在同一地址碼所標(biāo)識的區(qū)域范圍內(nèi),對同年菲茬、同月吉挣、同日出生的人編定的順序號派撕, 順序碼的奇數(shù)分配給男性,偶數(shù)分配給女性听想。
* 5.校驗碼(第十八位數(shù))
* (1)十七位數(shù)字本體碼加權(quán)求和公式 S = Sum(Ai * Wi), i = 0, … , 16 腥刹,先對前17位數(shù)字的權(quán)求和
* Ai:表示第i位置上的身份證號碼數(shù)字值
* Wi:表示第i位置上的加權(quán)因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
* (2)計算模 Y = mod(S, 11)
* (3)通過模得到對應(yīng)的校驗碼 Y: 0 1 2 3 4 5 6 7 8 9 10 校驗碼: 1 0 X 9 8 7 6 5 4 3 2
*/
if (identityString.length != 18) return NO;
// 正則表達(dá)式判斷基本 身份證號是否滿足格式
NSString *regex2 = @"^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$";
NSPredicate *identityStringPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
//如果通過該驗證,說明身份證格式正確汉买,但準(zhǔn)確性還需計算
if(![identityStringPredicate evaluateWithObject:identityString]) return NO;
//** 開始進(jìn)行校驗 *//
//地址校驗
/**
* 省衔峰、直轄市代碼表:
* 11 : 北京 12 : 天津 13 : 河北 14 : 山西 15 : 內(nèi)蒙古
* 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 : 國外
*/
NSArray * cityCodeArray = @[
@"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 *codeString= [identityString substringWithRange:NSMakeRange(0, 2)];
if (![cityCodeArray containsObject:codeString]) return NO;
//將前17位加權(quán)因子保存在數(shù)組里
NSArray *idCardWiArray = @[@"7", @"9", @"10", @"5", @"8", @"4", @"2", @"1", @"6", @"3", @"7", @"9", @"10", @"5", @"8", @"4", @"2"];
//這是除以11后,可能產(chǎn)生的11位余數(shù)蛙粘、驗證碼垫卤,也保存成數(shù)組
NSArray *idCardYArray = @[@"1", @"0", @"10", @"9", @"8", @"7", @"6", @"5", @"4", @"3", @"2"];
//用來保存前17位各自乖以加權(quán)因子后的總和
NSInteger idCardWiSum = 0;
for(int i = 0;i < 17;i++) {
NSInteger subStrIndex = [[identityString substringWithRange:NSMakeRange(i, 1)] integerValue];
NSInteger idCardWiIndex = [[idCardWiArray objectAtIndex:i] integerValue];
idCardWiSum+= subStrIndex * idCardWiIndex;
}
//計算出校驗碼所在數(shù)組的位置
NSInteger idCardMod=idCardWiSum%11;
//得到最后一位身份證號碼
NSString *idCardLast= [identityString substringWithRange:NSMakeRange(17, 1)];
//如果等于2,則說明校驗碼是10出牧,身份證號碼最后一位應(yīng)該是X
if(idCardMod==2) {
if(![idCardLast isEqualToString:@"X"]||[idCardLast isEqualToString:@"x"]) {
return NO;
}
}
else{
//用計算出的驗證碼與最后一位身份證號碼匹配穴肘,如果一致,說明通過舔痕,否則是無效的身份證號碼
if(![idCardLast isEqualToString: [idCardYArray objectAtIndex:idCardMod]]) {
return NO;
}
}
return YES;
}
由于最近在寫一丟丟前端评抚,順便貼一下JS的邏輯判定代碼,原理相似:
/**
* 校驗身份證
* @param {Object} idStr
*/
function checkIdstr (idStr) {
if ((idStr.length != 18)) {
return false;
}
var cityCodeArr = [ "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" ];
var cityCodeStr = idStr.substr(0,2);
var contain = $.inArray(cityCodeStr, cityCodeArr);
if (contain =="-1") {
return false;
}
var regex = RegExp("^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$");
if (regex.test(idStr) == false) {
return false;
}
var idCardArr = ["7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"];
var idCardYArr = ["1", "0", "10", "9", "8", "7", "6", "5", "4", "3", "2"];
var idCardWiSum = 0;
for (var i = 0; i < 17; i++) {
var subStrIndexStr = idStr.substr(i,1);
var idCardWiIndexStr = idCardArr[i];
idCardWiSum += parseInt(subStrIndexStr)*parseInt(idCardWiIndexStr);
}
var idCardMod = idCardWiSum % 11;
var idCardLast = idStr.substr(17,1);
if (idCardMod ==2) {
if (idCardLast != "X"||idCardLast != "x") {
return false;
}
} else{
if (idCardLast != idCardYArr[idCardMod]) {
return false;
}
}
}