修改身份证号的实现

1.x.x
ZhouXY108 2024-12-02 18:30:38 +08:00
parent 274f2d9874
commit cca3c8b1ee
3 changed files with 57 additions and 39 deletions

View File

@ -16,26 +16,39 @@
package xyz.zhouxy.plusone.commons.model;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.Immutable;
import xyz.zhouxy.plusone.commons.annotation.ReaderMethod;
import xyz.zhouxy.plusone.commons.annotation.ValueObject;
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
import xyz.zhouxy.plusone.commons.util.AssertTools;
import xyz.zhouxy.plusone.commons.util.StringTools;
/**
* Chinese2ndGenIDCardNumber
*
* <p>
*
* </p>
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
* @since 1.0
* @see xyz.zhouxy.plusone.commons.constant.PatternConsts#CHINESE_2ND_ID_CARD_NUMBER
*/
@ValueObject
@Immutable
public class Chinese2ndGenIDCardNumber extends IDCardNumber {
public class Chinese2ndGenIDCardNumber implements IDCardNumber, Serializable {
private final String value;
/** 省份编码 */
private final String provinceCode;
@ -52,7 +65,7 @@ public class Chinese2ndGenIDCardNumber extends IDCardNumber {
private Chinese2ndGenIDCardNumber(String value, String provinceCode, String cityCode, String countyCode,
Gender gender, LocalDate birthDate) {
super(value);
this.value = value;
this.provinceCode = provinceCode;
this.cityCode = cityCode;
this.countyCode = countyCode;
@ -60,13 +73,11 @@ public class Chinese2ndGenIDCardNumber extends IDCardNumber {
this.birthDate = birthDate;
}
public static final Pattern PATTERN = Pattern.compile("^(?<county>(?<city>(?<province>\\d{2})\\d{2})\\d{2})(?<birthDate>\\d{8})\\d{2}(?<gender>\\d)([\\dXx])$");
public static Chinese2ndGenIDCardNumber of(final String value) {
AssertTools.checkArgument(StringTools.isNotBlank(value), "二代居民身份证校验失败:号码为空");
final String idNumber = value.toUpperCase();
final Matcher matcher = Chinese2ndGenIDCardNumber.PATTERN.matcher(idNumber);
final Matcher matcher = PatternConsts.CHINESE_2ND_ID_CARD_NUMBER.matcher(idNumber);
AssertTools.checkArgument(matcher.matches(), () -> "二代居民身份证校验失败:" + value);
final String provinceCode = matcher.group("province");
@ -98,39 +109,53 @@ public class Chinese2ndGenIDCardNumber extends IDCardNumber {
// #region - reader methods
// ================================
@ReaderMethod
public String value() {
return value;
}
@ReaderMethod
public String getProvinceCode() {
return provinceCode;
}
@ReaderMethod
public String getProvinceName() {
return PROVINCE_CODES.get(this.provinceCode);
}
@ReaderMethod
public String getFullProvinceCode() {
return Strings.padEnd(this.provinceCode, 12, '0');
}
@ReaderMethod
public String getCityCode() {
return cityCode;
}
@ReaderMethod
public String getFullCityCode() {
return Strings.padEnd(this.cityCode, 12, '0');
}
@ReaderMethod
public String getCountyCode() {
return countyCode;
}
@ReaderMethod
public String getFullCountyCode() {
return Strings.padEnd(this.countyCode, 12, '0');
}
@ReaderMethod
@Override
public Gender getGender() {
return gender;
}
@ReaderMethod
@Override
public LocalDate getBirthDate() {
return birthDate;
@ -188,11 +213,18 @@ public class Chinese2ndGenIDCardNumber extends IDCardNumber {
@Override
public int hashCode() {
return super.hashCode();
return Objects.hashCode(value);
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
if (this == obj)
return true;
if (!(obj instanceof Chinese2ndGenIDCardNumber))
return false;
Chinese2ndGenIDCardNumber other = (Chinese2ndGenIDCardNumber) obj;
return Objects.equals(value, other.value);
}
private static final long serialVersionUID = 20241202095400L;
}

View File

@ -19,42 +19,31 @@ package xyz.zhouxy.plusone.commons.model;
import java.time.LocalDate;
import java.time.Period;
import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.util.AssertTools;
/**
*
*/
public abstract class IDCardNumber {
public interface IDCardNumber {
@Nonnull
private final String value;
static final char DEFAULT_REPLACED_CHAR = '*';
static final int DEFAULT_DISPLAY_FRONT = 1;
static final int DEFAULT_DISPLAY_END = 2;
private static final char DEFAULT_REPLACED_CHAR = '*';
private static final int DEFAULT_DISPLAY_FRONT = 1;
private static final int DEFAULT_DISPLAY_END = 2;
protected IDCardNumber(String value) {
this.value = value;
}
public final String getValue() {
return this.value;
}
String value();
/**
*
*/
public abstract Gender getGender();
Gender getGender();
/**
*
*/
public abstract LocalDate getBirthDate();
LocalDate getBirthDate();
/** 计算年龄 */
public final int calculateAge() {
default int calculateAge() {
LocalDate now = LocalDate.now();
return Period.between(getBirthDate(), now).getYears();
}
@ -63,23 +52,19 @@ public abstract class IDCardNumber {
// #region - toString
// ================================
@Override
public String toString() {
return toDesensitizedString();
}
public String toDesensitizedString() {
default String toDesensitizedString() {
return toDesensitizedString(DEFAULT_REPLACED_CHAR, DEFAULT_DISPLAY_FRONT, DEFAULT_DISPLAY_END);
}
public String toDesensitizedString(int front, int end) {
default String toDesensitizedString(int front, int end) {
return toDesensitizedString(DEFAULT_REPLACED_CHAR, front, end);
}
public String toDesensitizedString(char replacedChar, int front, int end) {
default String toDesensitizedString(char replacedChar, int front, int end) {
final String value = value();
AssertTools.checkArgument(front >= 0 && end >= 0);
AssertTools.checkArgument((front + end) <= this.value.length(), "需要截取的长度不能大于身份证号长度");
final char[] charArray = getValue().toCharArray();
AssertTools.checkArgument((front + end) <= value.length(), "需要截取的长度不能大于身份证号长度");
final char[] charArray = value.toCharArray();
for (int i = front; i < charArray.length - end; i++) {
charArray[i] = replacedChar;
}

View File

@ -26,13 +26,14 @@ import java.util.regex.Matcher;
import org.junit.jupiter.api.Test;
import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
@Slf4j
public class Chinese2ndGenIDCardNumberTests {
@Test
void testPattern() {
Matcher matcher = Chinese2ndGenIDCardNumber.PATTERN.matcher("11010520000101111X");
Matcher matcher = PatternConsts.CHINESE_2ND_ID_CARD_NUMBER.matcher("11010520000101111X");
assertTrue(matcher.matches());
for (int i = 0; i < matcher.groupCount(); i++) {
log.info("{}: {}", i, matcher.group(i));
@ -42,7 +43,7 @@ public class Chinese2ndGenIDCardNumberTests {
@Test
void test() {
Chinese2ndGenIDCardNumber idCardNumber = Chinese2ndGenIDCardNumber.of("11010520000101111X");
assertEquals("11010520000101111X", idCardNumber.getValue());
assertEquals("11010520000101111X", idCardNumber.value());
assertEquals(LocalDate.of(2000, 1, 1), idCardNumber.getBirthDate());
assertEquals(Gender.MALE, idCardNumber.getGender());
assertEquals("110105", idCardNumber.getCountyCode());