Skip to content

Commit f76c0d2

Browse files
committed
feat: add Chinese ID card validation expectation
1 parent b77da1f commit f76c0d2

2 files changed

Lines changed: 94 additions & 0 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from great_expectations.expectations.expectation import ColumnMapExpectation
2+
from great_expectations.render import RenderedStringTemplateContent
3+
from great_expectations.render.util import num_to_str, substitute_none_for_missing
4+
5+
6+
class ExpectColumnValuesToBeValidChineseIdCard(ColumnMapExpectation):
7+
"""
8+
验证列中的值为有效的中国居民身份证号
9+
- 支持15位(旧版)和18位(新版)身份证
10+
- 18位身份证会自动验证校验位
11+
- 简单验证出生日期格式
12+
"""
13+
14+
examples = [
15+
{
16+
"data": {
17+
"valid_ids": ["110105199003077753", "110105900307775"],
18+
"invalid_ids": ["123456", "110105199003077759", "abcdefg"],
19+
},
20+
"tests": [
21+
{
22+
"title": "测试有效身份证",
23+
"exact_match_out": False,
24+
"in": {"column": "valid_ids"},
25+
"out": {"success": True},
26+
},
27+
{
28+
"title": "测试无效身份证",
29+
"exact_match_out": False,
30+
"in": {"column": "invalid_ids"},
31+
"out": {"success": False},
32+
},
33+
],
34+
}
35+
]
36+
37+
map_metric = "column_values.valid_chinese_id_card"
38+
success_keys = ("mostly",)
39+
40+
@classmethod
41+
def _prescriptive_renderer(
42+
cls,
43+
configuration=None,
44+
runtime_configuration=None,
45+
**kwargs,
46+
):
47+
runtime_configuration = runtime_configuration or {}
48+
include_column_name = runtime_configuration.get("include_column_name", True)
49+
params = substitute_none_for_missing(
50+
configuration.kwargs,
51+
["column", "mostly", "row_condition", "condition_parser"],
52+
)
53+
54+
if params["mostly"] is not None and params["mostly"] < 1.0:
55+
params["mostly_pct"] = num_to_str(params["mostly"] * 100, precision=4, no_scientific=True)
56+
template_str = "值必须为有效的中国身份证号,至少 $mostly_pct % 的时间满足。"
57+
else:
58+
template_str = "值必须为有效的中国身份证号。"
59+
60+
if include_column_name:
61+
template_str = "$column " + template_str
62+
63+
return [
64+
RenderedStringTemplateContent(
65+
**{
66+
"content_block_type": "string_template",
67+
"string_template": {
68+
"template": template_str,
69+
"params": params,
70+
},
71+
}
72+
)
73+
]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from great_expectations.expectations.expectation import ColumnMapExpectation
2+
import re
3+
4+
class ExpectColumnValuesToBeValidChineseIdCard(ColumnMapExpectation):
5+
"""验证中国身份证号(15位/18位)"""
6+
map_metric = "column_values.valid_chinese_id_card"
7+
success_keys = ("mostly",)
8+
9+
def validate_id(self, id_str: str) -> bool:
10+
if not isinstance(id_str, str):
11+
return False
12+
id_str = id_str.strip()
13+
if len(id_str) not in (15, 18):
14+
return False
15+
if len(id_str) == 18:
16+
if not re.match(r"^\d{17}[\dXx]$", id_str):
17+
return False
18+
else:
19+
if not re.match(r"^\d{15}$", id_str):
20+
return False
21+
return True

0 commit comments

Comments
 (0)