惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
aimingoo的专栏
aimingoo的专栏
I
InfoQ
C
Check Point Blog
IT之家
IT之家
MyScale Blog
MyScale Blog
Apple Machine Learning Research
Apple Machine Learning Research
Vercel News
Vercel News
Last Week in AI
Last Week in AI
GbyAI
GbyAI
P
Proofpoint News Feed
量子位
Stack Overflow Blog
Stack Overflow Blog
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
阮一峰的网络日志
阮一峰的网络日志
人人都是产品经理
人人都是产品经理
B
Blog
T
The Blog of Author Tim Ferriss
H
Help Net Security
云风的 BLOG
云风的 BLOG

博客园 - 愚

Revit:二开使用Sqlite保存本地数据,并配合EF6等ORM框架 Revity:查找并修改类型参数和实例参数 复习一下UML Revit:ElementFilter过滤器基类 Revit:Element、Reference、ReferenceIntersector、ReferenceWithContext的理解 Revit:使用代码如何发出选点、选对象指令 Reivt:过滤器FilteredElementIterator,采集器FilteredElementCollector Revit:Transaction事务 Revit:弄清楚Application、UIApplication、UIDocument 、Document、DocumentSet之间的关系 Revit:IExternalCommand和IExternalApplication的区别 什么是假程序员 若我有一天 聊聊面试官那些事。。分享我的个人看法,认同的顶一顶。。。 分享一个自己写的取中国农历相关数据的类。包含:农历年月日,生肖,星座,年龄,天干,地支等方法 从结亲网 的架构谈起,谈什么架构, 我理解的架构。我想很多人理解的架构应该可能比较 狭义 面向对象的全套“企业微信”api接口的代码实现,网上太多“面向过程”微信api接口的代码,这个开源给需要的人用 解决:百度编辑器UEditor,怎么将图片保存到图片服务器,或者上传到ftp服务器的问题(如果你正在用UE,这篇文章值得你看下) (原创)面向对象的系统对接接口编写。第5篇(完结) (原创)面向对象的系统对接接口编写。第4篇
提供一个中国身份证号码判断的类
· 2019-04-06 · via 博客园 - 愚

本文章的目的是实现一个用于身份证号码判断是否有效的功能

首先,创建一个身份证基类:

    /// <summary>
    /// 中国大陆身份证
    /// </summary>
    public abstract class ChineseIdBase
    {
        /// <summary>
        /// 验证15位身份证号
        /// </summary>
        /// <param name="id">身份证号</param>
        /// <returns></returns>
        public abstract bool IsGrant(string id);

        /// <summary>
        /// 数字验证
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        protected abstract bool CheckNumber(string id);

        /// <summary>
        /// 省市区区域校验,身份前2位拿来判断
        /// </summary>
        /// <param name="code">比对码</param>
        protected virtual bool CheckAddress(string id)
        {
            string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
            if (address.IndexOf(id.Remove(2)) == -1)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 针对15位身份证校验生日。取身份证上的第7-14位字符来判断
        /// </summary>
        /// <param name="id">身份证号</param>
        /// <returns></returns>
        protected abstract bool CheckBirth(string id);
    }

身份证有分15位,和18位两种。

下面先实现15位身份证的子类:

    /// <summary>
    /// 中国大陆身份证判断。用于15位判断
    /// 
    /// <see cref="!:https://blog.csdn.net/s1102379635/article/details/7967179"/>
    /// <see cref="!:https://blog.csdn.net/qq_26545305/article/details/75042982"/>
    /// 
    /// 前1、2位数字表示:所在省(直辖市、自治区)的代码;
    /// 第3、4位数字表示:所在地级市(自治州)的代码;
    /// 第5、6位数字表示:所在区(县、自治县、县级市)的代码;
    /// 第7—14位数字表示:出生年、月、日;
    /// 第15、16位数字表示:所在地的派出所的代码(身份证背面的签发机关);
    /// 第17位数字表示性别:奇数表示男性,偶数表示女性;
    /// 第18位数字是校检码(个人信息码)(有的人是可能是x,这代表的是10罗马数字);
    /// </summary>
    public class ChineseId15Bit : ChineseIdBase
    {
        /// <summary>
        /// 验证15位身份证号
        /// </summary>
        /// <param name="id">身份证号</param>
        /// <returns>验证成功为True,否则为False</returns>
        public override bool IsGrant(string id)
        {
            if (string.IsNullOrWhiteSpace(id))
            {
                return false;
            }
            if (id.Length != 15)
            {
                return false;
            }

            //数字校验
            if (!this.CheckNumber(id)) { return false; }
            //省市区区域校验,身份前2位拿来判断
            if (!this.CheckAddress(id)) { return false; }
            //针对15位身份证校验生日。取身份证上的第7-14位字符来判断
            if (!this.CheckBirth(id)) { return false; }

            return true;//符合15位身份证标准
        }

        /// <summary>
        /// 数字验证
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        protected override bool CheckNumber(string id)
        {
            if (long.TryParse(id, out long n) == false || n < Math.Pow(10, 14))
            {
                return false;//数字验证
            }

            return true;
        }

        /// <summary>
        /// 针对15位身份证校验生日。取身份证上的第7-14位字符来判断
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        protected override bool CheckBirth(string id)
        {
            string birth = id.Substring(6, 6).Insert(4, "-").Insert(2, "-");
            DateTime time = new DateTime();
            if (DateTime.TryParse(birth, out time) == false)
            {
                return false;//生日验证
            }

            return true;
        }
    }

然后再写一个18位身份证的判断类:

    /// <summary>
    /// 中国大陆身份证判断。用于18位判断
    /// 
    /// <see cref="!:https://blog.csdn.net/s1102379635/article/details/7967179"/>
    /// <see cref="!:https://blog.csdn.net/qq_26545305/article/details/75042982"/>
    /// 
    /// 前1、2位数字表示:所在省(直辖市、自治区)的代码;
    /// 第3、4位数字表示:所在地级市(自治州)的代码;
    /// 第5、6位数字表示:所在区(县、自治县、县级市)的代码;
    /// 第7—14位数字表示:出生年、月、日;
    /// 第15、16位数字表示:所在地的派出所的代码(身份证背面的签发机关);
    /// 第17位数字表示性别:奇数表示男性,偶数表示女性;
    /// 第18位数字是校检码(个人信息码)(有的人是可能是x,这代表的是10罗马数字);
    /// </summary>
    public class ChineseId18Bit : ChineseIdBase
    {
        /// <summary>
        /// 验证18位身份证号
        /// </summary>
        /// <param name="id">身份证号</param>
        /// <returns>验证成功为True,否则为False</returns>
        public override bool IsGrant(string id)
        {
            if (string.IsNullOrWhiteSpace(id))
            {
                return false;
            }
            if (id.Length != 18)
            {
                return false;
            }

            //数字校验
            if (!this.CheckNumber(id)) { return false; }
            //省市区区域校验,身份前2位拿来判断
            if (!this.CheckAddress(id)) { return false; }
            //生日验证
            if (!this.CheckBirth(id)) { return false; }
            //判断校验码
            if (!this.CheckVerifyCode(id)) { return false; }

            return true;//符合GB11643-1999标准
        }

        /// <summary>
        /// 数字验证
        /// </summary>
        /// <param name="id">身份证号</param>
        /// <returns></returns>
        protected override bool CheckNumber(string id)
        {
            if (long.TryParse(id.Remove(17), out long n) == false || n < Math.Pow(10, 16) || long.TryParse(id.Replace('x', '0').Replace('X', '0'), out n) == false)
            {
                return false;//数字验证
            }

            return true;
        }

        /// <summary>
        /// 针对15位身份证校验生日。取身份证上的第7-14位字符来判断
        /// </summary>
        /// <param name="id">身份证号</param>
        /// <returns></returns>
        protected override bool CheckBirth(string id)
        {
            string birth = id.Substring(6, 8).Insert(6, "-").Insert(4, "-");
            DateTime time = new DateTime();
            if (DateTime.TryParse(birth, out time) == false)
            {
                return false;//生日验证
            }

            return true;
        }

        /// <summary>
        /// 检测检验码
        /// </summary>
        /// <param name="id">身份证号</param>
        /// <returns></returns>
        private bool CheckVerifyCode(string id)
        {
            string[] vi = ("1,0,x,9,8,7,6,5,4,3,2").Split(',');
            string[] wi = ("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2").Split(',');
            char[] ai = id.Remove(17).ToCharArray();
            int sum = 0;
            for (int i = 0; i < 17; i++)
            {
                sum += int.Parse(wi[i]) * int.Parse(ai[i].ToString());
            }
            int y = -1;
            Math.DivRem(sum, 11, out y);
            if (vi[y] != id.Substring(17, 1).ToLower())
            {
                return false;//校验码验证
            }

            return true;
        }
    }

最后,编写一个管理类,用于统一给外部方法调用 ,当然,你也可以不用这么做,直接实例化15位或者18位的身份证判断类,去实现自己的逻辑:

    /// <summary>
    /// 身份证管理
    /// </summary>
    public class ChineseIdManager : ITransient
    {
        /// <summary>
        /// 判断身份证是否验证通过
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> IsGrant(string id)
        {
            if (string.IsNullOrWhiteSpace(id))
            {
                throw new ArgumentNullException(nameof(id));
            }

            ChineseIdBase checker = null;
            var len = id.Length;
            if (len == 15)
            {
                checker = new ChineseId15Bit();
            }
            else if (len == 18)
            {
                checker = new ChineseId18Bit();
            }
            else
            {
                throw new UserFriendlyException("身份证号码错误");
            }

            return await Task.FromResult(checker.IsGrant(id));
        }
    }

客户端如何调用上述的类及方法呢:

        /// <summary>
        /// 检查身份证号码是否被ps修改过
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private async Task CheckId(string id)
        {
            if (!await this._chineseIdManager.IsGrant(id))
            {
                throw new UserFriendlyException("身份证号码格式错误");
            }
        }

如上,即可实现调用和判断。