Last active
May 16, 2018 03:46
-
-
Save chochinlu/2b305dfd1ede28a27fe21c833215d019 to your computer and use it in GitHub Desktop.
驗證與產生可用的身分證字號
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// wiki 身分證驗證規則 https://zh.wikipedia.org/wiki/%E4%B8%AD%E8%8F%AF%E6%B0%91%E5%9C%8B%E5%9C%8B%E6%B0%91%E8%BA%AB%E5%88%86%E8%AD%89#%E7%B7%A8%E8%99%9F%E8%A6%8F%E5%89%87 | |
// 中華民國身分證字號英文字首的編號規則數字 | |
const firstLetterMapping = new Map([ | |
['A', '10'], | |
['B', '11'], | |
['C', '12'], | |
['D', '13'], | |
['E', '14'], | |
['F', '15'], | |
['G', '16'], | |
['H', '17'], | |
['I', '34'], | |
['J', '18'], | |
['K', '19'], | |
['M', '21'], | |
['N', '22'], | |
['O', '35'], | |
['P', '23'], | |
['Q', '24'], | |
['T', '27'], | |
['U', '28'], | |
['V', '29'], | |
['W', '32'], | |
['X', '30'], | |
['Z', '33'], | |
['L', '20'], | |
['R', '25'], | |
['S', '26'], | |
['Y', '31'] | |
]); | |
// 驗證規則需要相乘的數 | |
const authMultiplier = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1]; | |
const checkPid = pid => { | |
// 長度要為10 | |
if (pid.length !== 10) return {result: false, msg: '身分證字號長度不正確'}; | |
// 開頭第一個為英文字母, 後為9個阿拉伯數字, 第一個數字拿來區分性別,男性為1、女性為2 | |
const re = /^[A-Za-z][12]\d{8}/; | |
if (!re.test(pid)) return {result: false, msg: '身分證格式錯誤'}; | |
// 驗證規則 | |
const [first, ...nums] = [...pid]; | |
const source = [...firstLetterMapping.get(first.toUpperCase()), ...nums] | |
.map((value, i) => value * authMultiplier[i]) | |
.reduce((a, b) => a + b, 0); | |
if (source % 10 !== 0) return {result: false, msg: '驗證失敗'}; | |
return {result: true}; | |
}; | |
const keys = [...firstLetterMapping.keys()]; | |
const genders = [1, 2]; | |
const nums = [...Array(10).keys()]; | |
const times = [...Array(8).keys()]; // for count | |
const genRestNums = () => { | |
let restNum = []; | |
times.forEach(v => { | |
restNum.push(nums[Math.floor(Math.random() * nums.length)]); | |
}); | |
return restNum.reduce((a, b) => a.toString() + b.toString(), ''); | |
}; | |
// 產生可用的身分證字號 | |
const genPid = () => { | |
// gen first letter | |
const key = keys[Math.floor(Math.random() * keys.length)]; | |
// gen second number 1 or 2 | |
const firstNum = genders[Math.floor(Math.random() * genders.length)]; | |
const id = `${key}${firstNum}${genRestNums()}`; | |
const {result} = checkPid(id); | |
return result ? id : genPid(); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment