标签:
中华人民共和国国家标准《GB 11643-1999 公民身份号码》的主要内容如下:
校验码的计算方法为:
公民身份证号码在很多程序中都会用到。所以,我写了一个助手类,如下所示:
using System; using System.Globalization; using System.Diagnostics; namespace Skyiv.Ben.Common { /// <summary> /// 中华人民共和国居民身份证 /// </summary> public sealed class Idcard { [Flags] public enum VerifyMode { None = 0, CheckNumber = 1, Date = 2, Full = CheckNumber | Date } public VerifyMode Mode { get; private set; } public DateTime MaxDate { get; private set; } public static readonly Idcard None = new Idcard(VerifyMode.None); public static readonly Idcard CheckNumber = new Idcard(VerifyMode.CheckNumber); public static readonly Idcard Date = new Idcard(VerifyMode.Date); public static readonly Idcard Full = new Idcard(VerifyMode.Full); static readonly byte[] weight = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }; static readonly string code = "10X98765432"; static readonly DateTime MinDate = new DateTime(1800, 1, 1); public Idcard(VerifyMode mode) : this(mode, DateTime.MaxValue) { } public Idcard(VerifyMode mode, DateTime maxDate) { Mode = mode; MaxDate = maxDate; } public long String2Number(string s) { long n; string msg; if (!TryString2Number(s, out n, out msg)) throw new ArgumentOutOfRangeException(msg, (Exception)null); return n; } public string Number2String(long n) { return (n == 0) ? "" : (Math.Abs(n).ToString() + ((n < 0) ? "X" : "")); } public bool TryString2Number(string s, out long n, out string msg) { if ((msg = TryString2Number(s, out n)) == null) return true; msg = "身份证号(" + s + ")" + msg; return false; } public string Convert15to18(string oldId) { string newId; if (!TryConvert15to18(oldId, out newId)) throw new ArgumentOutOfRangeException(newId, (Exception)null); return newId; } public bool TryConvert15to18(string oldId, out string newId) { if (oldId != null && oldId.Length == 18 && oldId.StartsWith("000")) oldId = oldId.Substring(3); long n; if (!TryString2Number(oldId, out n, out newId)) return false; newId = oldId; if (oldId.Length == 18) return true; Debug.Assert(oldId.Length == 15); newId = oldId.Substring(0, 6) + GetDateStr(oldId) + oldId.Substring(12); newId += GetCheckNumber(newId); return true; } string TryString2Number(string s, out long n) { n = 0; if (s == null) return "不能为空"; string msg; if ((msg = VerifyBase(s)) != null) return msg; if (Has(VerifyMode.CheckNumber) && (msg = VerifyCheckNumber(s)) != null) return msg; if (Has(VerifyMode.Date) && (msg = VerifyDate(s)) != null) return msg; Debug.Assert(s.Length == 15 || s.Length == 18); if (s.Length == 18 && !char.IsDigit(s, 17)) s = "-" + s.Substring(0, 17); n = long.Parse(s); return msg; } string VerifyBase(string s) { if (s.Length != 15 && s.Length != 18) return "必须是(15)或者(18)位"; if (s[0] == ‘0‘) return "不能以零开头"; for (int i = 0; i < s.Length; i++) if (i == 17 && !char.IsDigit(s, i) && s[i] != ‘x‘ && s[i] != ‘X‘) return "第(18)位必须是数字或者(x)或者(X)"; else if (i != 17 && !char.IsDigit(s, i)) return "除第(18)位外必须是数字"; return null; } string VerifyCheckNumber(string s) { Debug.Assert(s.Length == 15 || s.Length == 18); if (s.Length != 18 || char.ToUpper(s[17]) == GetCheckNumber(s)) return null; return "校验码错"; } string VerifyDate(string s) { Debug.Assert(s.Length == 15 || s.Length == 18); var dateStr = GetDateStr(s); DateTime date; if (!DateTime.TryParseExact(dateStr, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out date)) return "日期不合法"; if (date < MinDate) return "日期太小"; if (date > MaxDate) return "日期太大"; return null; } string GetDateStr(string s) { var dateStr = (s.Length == 18) ? "" : ((int.Parse(s.Substring(12, 3)) > 995) ? "18" : "19"); return dateStr + s.Substring(6, (s.Length == 18) ? 8 : 6); } char GetCheckNumber(string s) { Debug.Assert(s.Length == 17 || s.Length == 18); var sum = 0; for (var i = 0; i < weight.Length; i++) sum += weight[i] * (s[i] - ‘0‘); return code[sum % 11]; } bool Has(VerifyMode mode) { return (Mode & mode) == mode; } } }
示例程序如下所示:
using System; using Skyiv.Ben.Common; namespace Skyiv.Ben { class Test { static void Main() { string[] idcards = { "123456", "123456950229002", "123456950228002", "070843199507012145", "37084-199507012145", "37084319950701214Y", "370843179912312147", "370843199507012145", "15022319871109212X", }; long n; string msg; foreach (var idcard in idcards) { var valid = Idcard.Full.TryString2Number(idcard, out n, out msg); Console.WriteLine("{0,-18}: {1}", idcard, valid ? "OK" : msg); } } } }
这个程序的输出结果是:
版权声明:本文为博主http://www.zuiniusn.com原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/u013948190/article/details/47121921