Skip to content

Commit

Permalink
feat(isIdentityCard): add support for zh-CN (#1281)
Browse files Browse the repository at this point in the history
* add support for zh-CN in isIdentityCard()

* feat: add isIdentityCard tests

* fix: edit isIdentityCard tests field an eslint fix(#1281)
  • Loading branch information
twodogegg authored Apr 18, 2020
1 parent 84f93fe commit 2193913
Show file tree
Hide file tree
Showing 7 changed files with 557 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Validator | Description
**isHexColor(str)** | check if the string is a hexadecimal color.
**isHSL(str)** | check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on [CSS Colors Level 4 specification](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).<br/><br/>Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: `hsl(200grad+.1%62%/1)`).
**isRgbColor(str, [, includePercentValues])** | check if the string is a rgb or rgba color.<br/><br/>`includePercentValues` defaults to `true`. If you don't want to allow to set `rgb` or `rgba` values with percents, like `rgb(5%,5%,5%)`, or `rgba(90%,90%,90%,.3)`, then set it to false.
**isIdentityCard(str [, locale])** | check if the string is a valid identity card code.<br/><br/>`locale` is one of `['ES', 'zh-TW', 'he-IL', 'ar-TN']` OR `'any'`. If 'any' is used, function will check if any of the locals match.<br/><br/>Defaults to 'any'.
**isIdentityCard(str [, locale])** | check if the string is a valid identity card code.<br/><br/>`locale` is one of `['ES', 'zh-TW', 'he-IL', 'ar-TN', 'zh-CN']` OR `'any'`. If 'any' is used, function will check if any of the locals match.<br/><br/>Defaults to 'any'.
**isIn(str, values)** | check if the string is in a array of allowed values.
**isInt(str [, options])** | check if the string is an integer.<br/><br/>`options` is an object which can contain the keys `min` and/or `max` to check the integer is within boundaries (e.g. `{ min: 10, max: 99 }`). `options` can also contain the key `allow_leading_zeroes`, which when set to false will disallow integer values with leading zeroes (e.g. `{ allow_leading_zeroes: false }`). Finally, `options` can contain the keys `gt` and/or `lt` which will enforce integers being greater than or less than, respectively, the value provided (e.g. `{gt: 1, lt: 4}` for a number between 1 and 4).
**isIP(str [, version])** | check if the string is an IP (version 4 or 6).
Expand Down
132 changes: 132 additions & 0 deletions es/lib/isIdentityCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,138 @@ var validators = {

return sum % 10 === 0;
},
'ar-TN': function arTN(str) {
var DNI = /^\d{8}$/; // sanitize user input

var sanitized = str.trim(); // validate the data structure

if (!DNI.test(sanitized)) {
return false;
}

return true;
},
'zh-CN': function zhCN(str) {
var provinceAndCitys = {
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 powers = ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2'];
var parityBit = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];

var checkAddressCode = function checkAddressCode(addressCode) {
var check = /^[1-9]\d{5}$/.test(addressCode);
if (!check) return false; // eslint-disable-next-line radix

return !!provinceAndCitys[Number.parseInt(addressCode.substring(0, 2))];
};

var checkBirthDayCode = function checkBirthDayCode(birDayCode) {
var check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(birDayCode);
if (!check) return false;
var yyyy = parseInt(birDayCode.substring(0, 4), 10);
var mm = parseInt(birDayCode.substring(4, 6), 10);
var dd = parseInt(birDayCode.substring(6), 10);
var xdata = new Date(yyyy, mm - 1, dd);

if (xdata > new Date()) {
return false; // eslint-disable-next-line max-len
} else if (xdata.getFullYear() === yyyy && xdata.getMonth() === mm - 1 && xdata.getDate() === dd) {
return true;
}

return false;
};

var getParityBit = function getParityBit(idCardNo) {
var id17 = idCardNo.substring(0, 17);
var power = 0;

for (var i = 0; i < 17; i++) {
// eslint-disable-next-line radix
power += parseInt(id17.charAt(i), 10) * Number.parseInt(powers[i]);
}

var mod = power % 11;
return parityBit[mod];
};

var checkParityBit = function checkParityBit(idCardNo) {
return getParityBit(idCardNo) === idCardNo.charAt(17).toUpperCase();
};

var check15IdCardNo = function check15IdCardNo(idCardNo) {
var check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo);
if (!check) return false;
var addressCode = idCardNo.substring(0, 6);
check = checkAddressCode(addressCode);
if (!check) return false;
var birDayCode = "19".concat(idCardNo.substring(6, 12));
check = checkBirthDayCode(birDayCode);
if (!check) return false;
return checkParityBit(idCardNo);
};

var check18IdCardNo = function check18IdCardNo(idCardNo) {
var check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo);
if (!check) return false;
var addressCode = idCardNo.substring(0, 6);
check = checkAddressCode(addressCode);
if (!check) return false;
var birDayCode = idCardNo.substring(6, 14);
check = checkBirthDayCode(birDayCode);
if (!check) return false;
return checkParityBit(idCardNo);
};

var checkIdCardNo = function checkIdCardNo(idCardNo) {
var check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo);
if (!check) return false;

if (idCardNo.length === 15) {
return check15IdCardNo(idCardNo);
} else if (idCardNo.length === 18) {
return check18IdCardNo(idCardNo);
}

return false;
};

return checkIdCardNo(str);
},
'zh-TW': function zhTW(str) {
var ALPHABET_CODES = {
A: 10,
Expand Down
144 changes: 142 additions & 2 deletions lib/isIdentityCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ var _assertString = _interopRequireDefault(require("./util/assertString"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }




var validators = {
ES: function ES(str) {
(0, _assertString.default)(str);
Expand Down Expand Up @@ -43,7 +46,7 @@ var validators = {

var id = sanitized;
var sum = 0,
incNum;
incNum;

for (var i = 0; i < id.length; i++) {
incNum = Number(id[i]) * (i % 2 + 1); // Multiply number by 1 or 2
Expand All @@ -53,6 +56,9 @@ var validators = {

return sum % 10 === 0;
},
'zh-CN': function zhCN(str) {
return zhCNidCardNoValidator.checkIdCardNo(str)
},
'zh-TW': function zhTW(str) {
var ALPHABET_CODES = {
A: 10,
Expand Down Expand Up @@ -123,5 +129,139 @@ function isIdentityCard(str, locale) {
throw new Error("Invalid locale '".concat(locale, "'"));
}


var zhCNidCardNoValidator = {
provinceAndCitys: { 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: '国外' },


powers: ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2'],


parityBit: ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'],


checkAddressCode: function (addressCode) {
var check = /^[1-9]\d{5}$/.test(addressCode)
if (!check) return false
if (zhCNidCardNoValidator.provinceAndCitys[parseInt(addressCode.substring(0, 2))]) {
return true
} else {
return false
}
},


checkBirthDayCode: function (birDayCode) {
var check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(birDayCode)
if (!check) return false
var yyyy = parseInt(birDayCode.substring(0, 4), 10)
var mm = parseInt(birDayCode.substring(4, 6), 10)
var dd = parseInt(birDayCode.substring(6), 10)
var xdata = new Date(yyyy, mm - 1, dd)
if (xdata > new Date()) {
return false
} else if ((xdata.getFullYear() === yyyy) && (xdata.getMonth() === mm - 1) && (xdata.getDate() === dd)) {
return true
} else {
return false
}
},


getParityBit: function (idCardNo) {
var id17 = idCardNo.substring(0, 17)

var power = 0
for (var i = 0; i < 17; i++) {
power += parseInt(id17.charAt(i), 10) * parseInt(zhCNidCardNoValidator.powers[i])
}

var mod = power % 11
return zhCNidCardNoValidator.parityBit[mod]
},

checkParityBit: function (idCardNo) {
var parityBit = idCardNo.charAt(17).toUpperCase()
if (zhCNidCardNoValidator.getParityBit(idCardNo) === parityBit) {
return true
} else {
return false
}
},


checkIdCardNo: function (idCardNo) {

var check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo)
if (!check) return false
if (idCardNo.length === 15) {
return zhCNidCardNoValidator.check15IdCardNo(idCardNo)
} else if (idCardNo.length === 18) {
return zhCNidCardNoValidator.check18IdCardNo(idCardNo)
} else {
return false
}
},

check15IdCardNo: function (idCardNo) {
var check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo)
if (!check) return false
var addressCode = idCardNo.substring(0, 6)
check = zhCNidCardNoValidator.checkAddressCode(addressCode)
if (!check) return false
var birDayCode = '19' + idCardNo.substring(6, 12)
check = zhCNidCardNoValidator.checkBirthDayCode(birDayCode)
if (!check) return false
return zhCNidCardNoValidator.checkParityBit(idCardNo)
},

check18IdCardNo: function (idCardNo) {
var check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo)
if (!check) return false
var addressCode = idCardNo.substring(0, 6)
check = zhCNidCardNoValidator.checkAddressCode(addressCode)
if (!check) return false
var birDayCode = idCardNo.substring(6, 14)
check = zhCNidCardNoValidator.checkBirthDayCode(birDayCode)
if (!check) return false
return zhCNidCardNoValidator.checkParityBit(idCardNo)
}
}

module.exports = exports.default;
module.exports.default = exports.default;
module.exports.default = exports.default;

Loading

0 comments on commit 2193913

Please sign in to comment.