📋 目录
一、工具类功能
校验中国大陆 18 位身份证号并解析出出生日期、性别、周岁、地区码与省份码,也能只按前 17 位算出应有的末位校验码,末位小写 x 与首尾空白自动处理。
二、所需环境
JDK 17或以上
三、方法与调用示例(按需调用)
🔢 方法序号:1
🎯 方法用途:
- 一句话判 18 位居民身份证号是否合法,不合法也只给 false
- 注册、实名校验这类「先拦一道再说」的入口用它,别用解析方法当校验
🧩 方法定义:public static boolean isValid(String idCard)
🗣️ 入参解释:public static boolean isValid(身份证号码)
📤 返回值解释:boolean,合法返回 true,其余一律 false
💡 边界口径:
- 依次核对 18 位格式、出生日期是否真实存在、出生年份是否不早于 1900 且不晚于今天、末位校验码是否一致
- 日期用 STRICT 解析,能拦掉 2 月 30 日、2021 年 2 月 29 日这种不存在的生日
- 首尾空白会被去掉,末位小写
x统一按大写X处理 - 不校验前 6 位地区码是否被真实划设,15 位一代身份证不支持
null、空白、长度不对都返回 false,不抛异常
🧪 方法示例:
isValid(SAMPLE_FEMALE)与isValid(SAMPLE_MALE)都拿到true- 末位小写的
isValid("11010519491231002x")拿到true - 两侧带空白的号码拿到
true,空白被先去掉 - 校验码算对但日期不存在的两个号码拿到
false、false - 少一位与 15 位一代证分别拿到
false、false isValid(null)拿到false
🔢 方法序号:2
🎯 方法用途:
- 从号码的 7-14 位取出生日期,返回
LocalDate - 算年龄、判断是否成年、按生日做营销时用
🧩 方法定义:public static LocalDate getBirthDate(String idCard)
🗣️ 入参解释:public static LocalDate getBirthDate(身份证号码)
📤 返回值解释:LocalDate,号码里写的出生日期
💡 边界口径:
- 号码非法直接抛
IllegalArgumentException,不做静默兜底 - 末位小写 x 一样能解析,不需要调用方先规范化
- 只做 STRICT 日期解析,不存在的生日在号码非法这条上就失败了
🧪 方法示例:
getBirthDate("11010519491231002x")拿到1949-12-31getBirthDate(SAMPLE_MALE)拿到1990-03-07getBirthDate("11010520210229001X")抛非法的身份证号码: 11010520210229001X
🔢 方法序号:3
🎯 方法用途:
- 按今天的日期算周岁,生日没过会减一岁
- 成年判断、年龄区间筛选这类即时计算用它
🧩 方法定义:public static int getAge(String idCard)
🗣️ 入参解释:public static int getAge(身份证号码)
📤 返回值解释:int,截至今天的周岁
💡 边界口径:
- 周岁按日历算,不是「年份相减」,生日没过不算长一岁
- 参考日期是 JVM 默认时区的今天,跨时区要自己传参考日期
- 号码非法同样抛
IllegalArgumentException
🧪 方法示例:
getAge(SAMPLE_MALE)拿到36,1990 年 3 月 7 日生,当天已过生日
🔢 方法序号:4
🎯 方法用途:
- 按指定参考日期算周岁,测试和「截至某日年龄」的口径都用它
- 结果需要可复现时别用无参考日期版,天天下飘
🧩 方法定义:public static int getAge(String idCard, LocalDate refDate)
🗣️ 入参解释:public static int getAge(身份证号码, 参考日期)
📤 返回值解释:int,截至参考日期的周岁
💡 边界口径:
- 生日当天算满岁,生日前一天还是上一岁
- 参考日期早于出生日期时按
Period语义给负数,异常数据要调用方自己判 refDate传 null 抛NullPointerException,号码非法抛IllegalArgumentException
🧪 方法示例:
getAge(SAMPLE_MALE, LocalDate.of(2026, 3, 6))拿到35 周岁,生日前一天getAge(SAMPLE_MALE, LocalDate.of(2026, 3, 7))拿到36 周岁,生日当天满岁getAge(SAMPLE_MALE, LocalDate.of(2027, 3, 6))拿到36 周岁,下一个生日前夜getAge(SAMPLE_MALE, null)抛refDate 不能为 null
🔢 方法序号:5
🎯 方法用途:
- 按第 17 位顺序码的奇偶取性别,奇数为男、偶数为女
- 填充用户资料、做人群分布统计时用
🧩 方法定义:public static String getGender(String idCard)
🗣️ 入参解释:public static String getGender(身份证号码)
📤 返回值解释:String,只给 男 或 女 两个字
💡 边界口径:
- 只看第 17 位,不看姓名与其他信息
- 号码非法抛
IllegalArgumentException - 返回的是中文文案,要存代码值自己映射
🧪 方法示例:
getGender(SAMPLE_FEMALE)拿到女,第 17 位是偶数getGender(SAMPLE_MALE)拿到男
🔢 方法序号:6
🎯 方法用途:
- 取号码前 6 位地区码原样返回
- 按户籍地做地域统计、区划码回填时用
🧩 方法定义:public static String getAreaCode(String idCard)
🗣️ 入参解释:public static String getAreaCode(身份证号码)
📤 返回值解释:String,前 6 位地区码字符串
💡 边界口径:
- 原样截取,不查区划字典,也不判断是否真实划设过
- 号码非法抛
IllegalArgumentException - 保留前导结构,需要省份码再走下一个方法
🧪 方法示例:
getAreaCode(SAMPLE_MALE)拿到110101
🔢 方法序号:7
🎯 方法用途:
- 取号码前 2 位省级行政区划码
- 按省聚合、做省份下拉回填时用这一版
🧩 方法定义:public static String getProvinceCode(String idCard)
🗣️ 入参解释:public static String getProvinceCode(身份证号码)
📤 返回值解释:String,前 2 位省级码
💡 边界口径:
- 只截前两位,不做省份名称映射,字典自己维护
- 号码非法抛
IllegalArgumentException - 与地区码是前缀关系,
11对应110101的省级段
🧪 方法示例:
getProvinceCode(SAMPLE_MALE)拿到11
🔢 方法序号:8
🎯 方法用途:
- 按 ISO 7064:1983 MOD 11-2 由前 17 位算出应有的末位校验码
- 生成测试号码、或者对端只给了前 17 位要补全时用
🧩 方法定义:public static char calculateCheckCode(CharSequence first17)
🗣️ 入参解释:public static char calculateCheckCode(前17位数字串)
📤 返回值解释:char,校验码字符,取值是 0-9 或 X
💡 边界口径:
- 长度不是 17 位、或含非数字字符都抛
IllegalArgumentException - 余值为 2 时校验码是
X,返回值可能是字母 - 只算校验位,不判断出生日期是否合法
🧪 方法示例:
calculateCheckCode("51010519700101001")拿到6,拼成 18 位后isValid是true- 国标样例的前 17 位算出
X,与号码末位一致 - 传 15 位串抛
前 17 位长度不正确: 15 - 前 17 位里夹一个字母抛
前 17 位必须全部为数字
四、工具类源码(可直接复制)
📦 源码文件