1
zj
2025-10-15 7372a8ebb182466728db91911bbbe28eaaea5a18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
package com.ruoyi.im.util;
 
import java.util.regex.Pattern;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
 
public class ValidatorUtil {
 
    // 手机号正则表达式(匹配中国大陆手机号)
    private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
 
    // 身份证号正则表达式(18位)
    private static final String ID_CARD_REGEX = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
 
    // 省份代码映射
    private static final Map<String, String> PROVINCE_CODES = new HashMap<>();
 
    static {
        // 初始化省份代码
        PROVINCE_CODES.put("11", "北京");
        PROVINCE_CODES.put("12", "天津");
        PROVINCE_CODES.put("13", "河北");
        PROVINCE_CODES.put("14", "山西");
        PROVINCE_CODES.put("15", "内蒙古");
        PROVINCE_CODES.put("21", "辽宁");
        PROVINCE_CODES.put("22", "吉林");
        PROVINCE_CODES.put("23", "黑龙江");
        PROVINCE_CODES.put("31", "上海");
        PROVINCE_CODES.put("32", "江苏");
        PROVINCE_CODES.put("33", "浙江");
        PROVINCE_CODES.put("34", "安徽");
        PROVINCE_CODES.put("35", "福建");
        PROVINCE_CODES.put("36", "江西");
        PROVINCE_CODES.put("37", "山东");
        PROVINCE_CODES.put("41", "河南");
        PROVINCE_CODES.put("42", "湖北");
        PROVINCE_CODES.put("43", "湖南");
        PROVINCE_CODES.put("44", "广东");
        PROVINCE_CODES.put("45", "广西");
        PROVINCE_CODES.put("46", "海南");
        PROVINCE_CODES.put("50", "重庆");
        PROVINCE_CODES.put("51", "四川");
        PROVINCE_CODES.put("52", "贵州");
        PROVINCE_CODES.put("53", "云南");
        PROVINCE_CODES.put("54", "西藏");
        PROVINCE_CODES.put("61", "陕西");
        PROVINCE_CODES.put("62", "甘肃");
        PROVINCE_CODES.put("63", "青海");
        PROVINCE_CODES.put("64", "宁夏");
        PROVINCE_CODES.put("65", "新疆");
        PROVINCE_CODES.put("71", "台湾");
        PROVINCE_CODES.put("81", "香港");
        PROVINCE_CODES.put("82", "澳门");
    }
 
    // 身份证校验码权重
    private static final int[] ID_CARD_WEIGHT = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
 
    // 身份证校验码对应值
    private static final char[] ID_CARD_CHECK_CODE = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
 
    /**
     * 验证手机号格式
     * @param phone 手机号码
     * @return 是否有效
     */
    public static boolean isValidPhone(String phone) {
        if (phone == null || phone.trim().isEmpty()) {
            return false;
        }
 
        // 移除可能的分隔符(如空格、短横线等)
        String cleanedPhone = phone.replaceAll("[\\s-]+", "");
 
        return Pattern.matches(PHONE_REGEX, cleanedPhone);
    }
 
    /**
     * 验证身份证号格式
     * @param idCard 身份证号码
     * @return 是否有效
     */
    public static boolean isValidIdCard(String idCard) {
        if (idCard == null || idCard.trim().isEmpty()) {
            return false;
        }
 
        // 转换为大写以便统一处理
        String cleanedIdCard = idCard.trim().toUpperCase();
 
        // 基本格式校验
        if (!Pattern.matches(ID_CARD_REGEX, cleanedIdCard)) {
            return false;
        }
 
        // 校验省份代码
        String provinceCode = cleanedIdCard.substring(0, 2);
        if (!PROVINCE_CODES.containsKey(provinceCode)) {
            return false;
        }
 
        // 校验生日日期
        if (!isValidBirthday(cleanedIdCard.substring(6, 14))) {
            return false;
        }
 
        // 校验校验码
        return isValidCheckCode(cleanedIdCard);
    }
 
    /**
     * 验证身份证中的生日日期是否有效
     * @param birthdayStr 生日字符串(YYYYMMDD格式)
     * @return 是否有效
     */
    private static boolean isValidBirthday(String birthdayStr) {
        try {
            int year = Integer.parseInt(birthdayStr.substring(0, 4));
            int month = Integer.parseInt(birthdayStr.substring(4, 6));
            int day = Integer.parseInt(birthdayStr.substring(6, 8));
 
            // 检查年份范围(假设身份证持有者年龄在0-150岁之间)
            int currentYear = Calendar.getInstance().get(Calendar.YEAR);
            if (year < currentYear - 150 || year > currentYear) {
                return false;
            }
 
            // 检查月份
            if (month < 1 || month > 12) {
                return false;
            }
 
            // 检查日期
            if (day < 1 || day > 31) {
                return false;
            }
 
            // 检查特定月份的天数
            if ((month == 4 || month == 6 || month == 9 || month == 11) && day > 30) {
                return false;
            }
 
            // 检查闰年二月
            if (month == 2) {
                boolean isLeapYear = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
                if (isLeapYear && day > 29) {
                    return false;
                }
                if (!isLeapYear && day > 28) {
                    return false;
                }
            }
 
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
 
    /**
     * 验证身份证校验码
     * @param idCard 身份证号码
     * @return 校验码是否正确
     */
    private static boolean isValidCheckCode(String idCard) {
        try {
            int sum = 0;
            for (int i = 0; i < 17; i++) {
                int digit = Character.getNumericValue(idCard.charAt(i));
                sum += digit * ID_CARD_WEIGHT[i];
            }
 
            int mod = sum % 11;
            char checkCode = ID_CARD_CHECK_CODE[mod];
 
            return checkCode == idCard.charAt(17);
        } catch (Exception e) {
            return false;
        }
    }
 
    /**
     * 测试方法
     */
    public static void main(String[] args) {
        // 测试手机号验证
        String[] testPhones = {
                "13800138000",
                "12345678901",
                "1861234567",
                "19612345678",
                " 138-0013-8000 ",
                "123abc45678"
        };
 
        System.out.println("手机号验证测试:");
        for (String phone : testPhones) {
            System.out.println(phone + " : " + isValidPhone(phone));
        }
 
        System.out.println("\n身份证验证测试:");
        // 测试身份证验证
        String[] testIdCards = {
                "11010519491231002X", // 有效身份证
                "123456789012345678", // 无效身份证
                "110105194902300021", // 无效日期(非闰年2月30日)
                "110105194913310022", // 无效月份
                "999999200001010000"  // 无效省份代码
        };
 
        for (String idCard : testIdCards) {
            System.out.println(idCard + " : " + isValidIdCard(idCard));
        }
    }
}