# -*- coding: utf-8 -*-
"""
@Time : 2021/9/9 15:00
@Author : Little Duo
@File : IDCardTools.py
http://www.mca.gov.cn/article/sj/xzqh/1980/
"""
import time
import random
from data import Area
from enum import Enum
from pydantic import BaseModel
class Verification(Enum):
PASSED = '验证通过'
LENGTH_ERROR = '身份证号码长度错误'
BIRTH_ERROR = '身份证号码出生日期校验错误'
VERITYCODE_ERROR = '身份证号码校验码错误'
AREACODE_ERROR = '身份证地区非法'
NULL_ERROR = '身份证号码不能为空'
class Result(BaseModel):
success: bool = True
desc: str
def calculVerityCode(seventeenIdCard):
"""
计算校验码
:param seventeenIdCard: 17位身份证号码
:return:
"""
i = 0
count = 0
weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] # 权重项
checkcode = {'0': '1', '1': '0', '2': 'X', '3': '9', '4': '8', '5': '7', '6': '6', '7': '5', '8': '5', '9': '3',
'10': '2'}
for i in range(0, 17):
count = count + int(seventeenIdCard[i]) * weight[i]
return checkcode[str(count % 11)] # 算出校验码
def checkIDCard(idCard: str):
"""
身份证号码校验(仅限大陆)
:param idCard:
:return:
"""
# 身份证号码位数校验
if len(idCard) not in (15, 18):
return Result(success=False, desc=Verification.LENGTH_ERROR.name)
# 地区校验
province = Area.province()
idCardList = list(idCard)
if idCard[0:2] not in province.keys():
return Result(success=False, desc=Verification.AREACODE_ERROR.name)
# 出生日期校验
birthday = '19{}'.format(idCard[6:-3]) if len(idCard) == 15 else idCard[6:-4]
try:
year = time.strptime(birthday, '%Y%m%d').tm_year
if year >= time.localtime().tm_year or year < 1900:
raise ValueError
except ValueError:
return Result(success=False, desc=Verification.BIRTH_ERROR.name)
if idCard[17] != calculVerityCode(idCard[:17]):
return Result(success=False, desc=Verification.VERITYCODE_ERROR.name)
return Result(desc=Verification.PASSED.name)
def gennerator(areaCode, year, month, day, gend):
"""
:param areaCode: 地区编码
:param year: 出生年
:param month: 出生月
:param day: 出生日
:param gend: 性别 1男2女
:return:
"""
gendCode = random.choice([0, 2, 4, 6, 8]) if int(gend) > 1 else random.choice([1, 3, 5, 7, 9])
idCard = '{}{}{}{}{}{}'.format(areaCode, year, month, day, random.randint(10, 99), gendCode)
idCard = idCard + calculVerityCode(idCard)
return idCard
def upEighteen(fifteenIDCard):
"""
15位转18位
:param fifteenIDCard:
:return:
"""
checkIDCarded = checkIDCard(fifteenIDCard)
if not checkIDCarded.success:
return checkIDCarded
seventeenIDCard = fifteenIDCard[0:6] + '19' + fifteenIDCard[6:15]
return seventeenIDCard + calculVerityCode(seventeenIDCard)
def downFifteen(eighteenIDCard):
"""
18位转15位
:param eighteenIDCard:18位身份证号码
:return:
"""
checkIDCarded = checkIDCard(eighteenIDCard)
if not checkIDCarded.success:
return checkIDCarded
return eighteenIDCard[0:6] + eighteenIDCard[8:17]