/// <summary>
/// 身份证
/// </summary>
[serializable]
public class idcard
{
    /// <summary>
    /// 身份证号
    /// </summary>
    public string idcardnum { get; set; }
    /// <summary>
    /// 行政区
    /// </summary>
    public string canton { get; private set; }
    /// <summary>
    /// 出生日期
    /// </summary>
    public datetime birthday { get; private set; }
    /// <summary>
    /// 性别(0-女;1-男)
    /// </summary>
    public int gander { get; private set; }
    /// <summary>
    /// 是否为合法身份证号
    /// </summary>
    public bool isidcard { get; private set; }
    public idcard() { }
    public idcard(string idnumber)
    {
        this.idcardnum = idnumber;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="number"></param>
    /// <returns></returns>
    public static idcard parse(string number)
    {
        idcard idcard = new idcard(number);
        const int s5bits = 15;
        const int s8bits = 18;
        #region 15位
        if (number.length == s5bits)  //15位的处理
        {
            //检查输入是否为数字
            for (int i = 0; i < number.length; i++)
            {
                if ((number[i] < '0') || (number[i] > '9'))
                {
                    throw new formatexception("身份证号错误");
                }
            }
            //出生日期
            string birthday = "19" + number.substring(6, 6);
            string year = birthday.substring(0, 4);
            string month = birthday.substring(4, 2);
            string day = birthday.substring(6, 2);
            birthday = string.format("{0}-{1}-{2}", year, month, day);
            datetime date = new datetime();
            if (datetime.tryparse(birthday, out date))
            {
                idcard.birthday = date;
            }
            else
            {
                throw new invalidcastexception("身份证号出生日期错误");
            }
            
            //性别
            if ((number[s5bits - 1] == '0') || (number[s5bits - 1] % 2 == 0))
            {
                idcard.gander = 0; // 女
            }
            else
            {
                idcard.gander = 1; // 男
            }
            idcard.isidcard = true;
            return idcard;
        }
        #endregion
        #region 18位
        else if (number.length == s8bits)  //18位的处理
        {
            // 检查前17位是否为数字
            for (int i = 0; i < number.length -1; i++)
            {
                if ((number[i] < '0') || (number[i] > '9'))
                {
                    throw new formatexception("身份证号错误");
                }
            }
            char end = number[s8bits - 1];  //最后一位
            //最后1位是x转成大写x
            if (end == 'x')
            {
                end = 'x';
                number = number.substring(0, s8bits - 1) + end;
            }
            if (!(end == 'x' || (end >= '0' && end <= '9')))
            {
                throw new formatexception("身份证号错误");
            }
            
            /// 校验
            int num = 0;
            char proof;
            for (int i = 17; i > 0; i--)
            {
                num = num + (int)(math.pow(2, i) % 11) * (number[17 - i] - 48);
            }
            num %= 11;
            switch (num)
            {
                case 0:
                    proof = '1';
                    break;
                case 1:
                    proof = '0';
                    break;
                case 2:
                    proof = 'x';
                    break;
                default:
                    proof = (char)(12 - num + 48);
                    break;
            }
            if (end != proof)  //最后一位与校验码不符
            {
                throw new formatexception("身份证号错误");
            }
            //出生日期
            string birthday = number.substring(6, 8);
            string year = birthday.substring(0, 4);
            string month = birthday.substring(4, 2);
            string day = birthday.substring(6, 2);
            birthday = string.format("{0}-{1}-{2}", year, month, day);
            datetime date = new datetime();
            if (datetime.tryparse(birthday, out date))
            {
                idcard.birthday = date;
            }
            else
            {
                throw new invalidcastexception("身份证号出生日期错误");
            }
            //行政区
            idcard.canton = number.substring(0, 6);
            //性别
            if ((number[16] == '0') || (number[16] % 2 == 0))
            {
                idcard.gander = 0;  //女
            }
            else
            {
                idcard.gander = 1;  //男
            }
            idcard.isidcard = true;
            return idcard;
        }
        #endregion
        else
        {
            throw new formatexception("无效的身份证号码位数:" + number.length);
        }
    }
    public static bool tryparse(string number, out idcard card)
    {
        idcard idcard = null;
        bool isidcard = true;
        try
        {
            parse(number);
        }
        catch (exception)
        {
            isidcard = false;
        }
        card = idcard;
        return isidcard;
    }
}