新旧身份证合法性验证及相互转换算法.txt遇事潇洒一点,看世糊涂一点。相亲是经销,恋爱叫直销,抛绣球招亲则为围标。没有准备请不要开始,没有能力请不要承诺。爱情这东西,没得到可能是缺憾,不表白就会有遗憾,可是如果自不量力,就只能抱憾了。新旧身份证合法性验证及相互转换算法
——谨以此文献给共事3年即将离职的PPL
作者:成晓旭
  前天,看到PPL在一个需要网站上注册,但该网站要求输入一个身份证号码,并且随便输入一个还不行:对方还要验证输入身份证的合法性,所以,烦得PPLselina怎么烧伤的在网上到处去。基于此目前,特别在网上收集身份证相关的资料,整理成文,作为给PPL饯行的礼物之一,公布于我的Blog。也预祝PPL:“份好工作,个好老婆!”
1、关于中国居民身份证的常识:
  我国现行使用公民身份证号码有两种尊循两个国家标准,〖GB 11643-1989〗和〖GB 11643-1999〗。
  〖GB 11643-1989〗中规定的是15位身份证号码:排列顺序从左至右依次为:六位数字地址码,六位数字出生日期码,三位数字顺序码,其中出生日期码不包含世纪数。
 
  〖GB 11643-1999〗中规定的是18位身份证号码:公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
 
  地址码:表示编码对象常住户口所在县(市、旗、区)的行政区划代码。
  出生日期码:表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。
  顺序码:表示同一地址码所标识的区域范围内,对同年、同月、同日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。
  校验码:是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。
关于身份证号码最后一位的校验码的算法如下:
 ∑(a[i]*W[i]) mod 11 ( i = 2, 3, ..., 18 )
   "*" 表示乘号
  i网站建设规划  表示身份证号码每一位的序号,从右至左,最左侧为18,最右侧为1
  a[i]蒋大为怎么了 表示身份证号码第 i 位上的号码
  W[i] 表示第 i 位上的权值 W[i] = 2^(i-1) mod 11
  设:R = (a[i]*W[i]) mod 11 ( i = 2, 3, ..., 18 )
  C = 身份证号码的校验码
  则RC之间的对应关系如下表:
   R0 1 2 3 4 5 6 7 8 9 10
   C1 0 X 9 8 7 6 5 4 3 2
  由此看出什么植物靠风传播种子 X 就是 10,罗马数字中的 10 就是X,所以在新标准的身份证号码中可能含有非数字的字母X
2、算法:
/** *//**
*
*/
package cxx.sourceCode.base;
DateFormat;
NumberFormat;
ParseException;
import java.util.Date;
import java.util.Random;
/** *//**
* @author 成晓旭
*
*/
public class Identity ...{
//    位权值数组
    private static byte[] Wi=new byte[17];
//    身份证前部分字符数
    private static final byte fPart = 6;
//    身份证算法求模关键值
    private static final byte fMod = 11;
//    旧身份证长度
    private static final byte oldIDLen = 15;
//    新身份证长度
    private static final byte newIDLen = 18;
//    新身份证年份标志
    private static final String yearFlag = "19";
//    校验码串
    private static final String CheckCode="10X98765432";
//    最小的行政区划码
    private static final int minCode = 150000;
//    最大的行政区划码
    private static final int maxCode = 700000;
//    旧身份证号码
//    private String oldIDCard="";
//    新身份证号码
//    private String newIDCard="";
//    地区及编码
   
   
    //private String Area[][2] =
    private static void setWiBuffer()...{200字摘抄
        for(int i=0;i<Wi.length;i++)...{   
            int k = (int) Math.pow(2, (Wi.length-i));
            Wi[i] = (byte)(k % fMod);
        }
    }
   
    //获取新身份证的最后一位:检验位
    private static String getCheckFlag(String idCard)...{
        int sum = 0;
        //进行加权求和
        for(int i=0; i<17; i++)...{       
            sum += Integer.parseInt(idCard.substring(i,i+1)) * Wi[i];
        }
        //取模运算,得到模值
        byte iCode = (byte) (sum % fMod);
        return CheckCode.substring(iCode,iCode+1);
    }
   
    //判断串长度的合法性
    private static boolean checkLength(final String idCard,boolean newIDFlag)...{
        boolean right = (idCard.length() == oldIDLen) || (idCard.length() == newIDLen);
        newIDFlag = false;
        if(right)...{
            newIDFlag = (idCard.length() == newIDLen);
        }
        return right;
    }
   
    //获取时间串
    private static String getIDDate(final String idCard,boolean newIDFlag)...{
        String dateStr = "";
        if(newIDFlag)
            dateStr = idCard.substring(fPart,fPart+8);
        else
            dateStr = yearFlag + idCard.substring(fPart,fPart+6);
        return dateStr;
    }
   
    //判断时间合法性
    private static boolean checkDate(final String dateSource)...{
        String dateStr = dateSource.substring(0,4)+"-"+dateSource.substring(4,6)+"-"+dateSource.substring(6,8);
        System.out.println(dateStr);
        DateFormat df = DateInstance();
        df.setLenient(false);
        try ...{
            Date date= df.parse(dateStr);
爱的表白词
            return (date!=null);
        } catch (ParseException e) ...{
            // TODO Auto-generated catch block
            return false;
        }
    }
   
    //旧身份证转换成新身份证号码
    public static String getNewIDCard(final String oldIDCard)...{
        //初始化方法
        Identity.setWiBuffer();
        if(!checkIDCard(oldIDCard))...{
            return oldIDCard;
        }
        String newIDCard = oldIDCard.substring(0, fPart);
        newIDCard += yearFlag;