lua身份证号码验证~

Posted more~power

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lua身份证号码验证~相关的知识,希望对你有一定的参考价值。

--验证身份证信息
--只支持18位身份证的验证

--[[
#身份证18位编码规则:dddddd yyyymmdd xxx y   
#dddddd:地区码   
#yyyymmdd: 出生年月日   
#xxx:顺序类编码,无法确定,奇数为男,偶数为女   
#y: 校验码,该位数值可通过前17位计算获得  
#<p />  
#18位号码加权因子为(从右到左) Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2,1 ]  
#验证位 Y = [ 1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2 ]   
#校验位计算公式:Y_P = mod( ∑(Ai×Wi),11 )   
#i为身份证号码从右往左数的 2...18 位; Y_P为脚丫校验码所在校验码数组位置  
参考代码:
      https://github.com/yujinqiu/idlint
]]
local string_len = string.len
local tonumber = tonumber

-- // wi =2(n-1)(mod 11) 
local wi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 }; 
-- // verify digit 
local vi= { 1, 0, X, 9, 8, 7, 6, 5, 4, 3, 2 }; 

local function isBirthDate(date)
    local year = tonumber(date:sub(1,4))
    local month = tonumber(date:sub(5,6))
    local day = tonumber(date:sub(7,8))
    if year < 1900 or year > 2100 or month >12 or month < 1 then
        return false
    end
    -- //月份天数表
    local month_days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    local bLeapYear = (year % 4 == 0 and year % 100 ~= 0) or (year % 400 == 0)
    if bLeapYear  then
        month_days[2] = 29;
    end

    if day > month_days[month] or day < 1 then
        return false
    end

    return true
end

local function isAllNumberOrWithXInEnd( str )
    local ret = str:match("%d+X?") 
    return ret == str 
end


local function checkSum(idcard)
    -- copy from http://stackoverflow.com/questions/829063/how-to-iterate-individual-characters-in-lua-string
    local nums = {}
    local _idcard = idcard:sub(1,17)
    for ch in _idcard:gmatch"." do
        table.insert(nums,tonumber(ch))
    end
    local sum = 0
    for i,k in ipairs(nums) do
        sum = sum + k * wi[i]
    end

    return vi [sum % 11+1] == idcard:sub(18,18 )
end


local err_success = 0
local err_length = 1
local err_province = 2
local err_birth_date = 3
local err_code_sum = 4
local err_unknow_charactor = 5

local function verifyIDCard(idcard)
    if string_len(idcard) ~= 18 then
        return err_length
    end

    if not isAllNumberOrWithXInEnd(idcard) then
        return err_unknow_charactor
    end
    -- //第1-2位为省级行政区划代码,[11, 65] (第一位华北区1,东北区2,华东区3,中南区4,西南区5,西北区6)
    local nProvince = tonumber(idcard:sub(1, 2))
    if( nProvince < 11 or nProvince > 65 ) then
        return err_province
    end

    -- //第3-4为为地级行政区划代码,第5-6位为县级行政区划代码因为经常有调整,这块就不做校验

    -- //第7-10位为出生年份;//第11-12位为出生月份 //第13-14为出生日期
    if not isBirthDate(idcard:sub(7,14)) then
        return err_birth_date
    end

    if not checkSum(idcard) then
        return err_code_sum
    end

    return err_success
end


local function UnitTest_CheckBirthDay()
    assert(isBirthDate(19881128) == true)
    assert(isBirthDate(19881328) == false)
    assert(isBirthDate(19881232) == false)
    assert(isBirthDate(19880229) == true)
    assert(isBirthDate(19880228) == true)
    assert(isBirthDate(18000228) == false)
    assert(isBirthDate(20000229) == true)
    assert(isBirthDate(21220228) == false)

end

local function UnitTest()
    print(begin UnitTest)
    UnitTest_CheckBirthDay()
    assert(verifyIDCard(411302198011276412) == err_code_sum)
    assert(verifyIDCard(4113021988112864x7) == err_unknow_charactor)
    assert(verifyIDCard(41130219881128641) == err_length)
end

UnitTest()

 

手游项目中需要实名需求,项目是lua写的,github上找了下没有找到lua的实现,只看到了c++,python,js.于是仿照其中的c++,移植到lua.

 

以上是关于lua身份证号码验证~的主要内容,如果未能解决你的问题,请参考以下文章

中国身份证号码验证原理

java验证身份证号码是否有效源代码

第二代身份证号码的验证代码

按GB 11643标准对大陆身份证号码分析验证

C#实现身份证号码验证的方法

编程乐趣:身份证号码验证的方法