Skip to content
This repository was archived by the owner on Jan 8, 2025. It is now read-only.

Commit 4a66ab3

Browse files
authored
Fixed #15 - implement Iran national id number (#222)
1 parent 07dd0ea commit 4a66ab3

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

idnumbers/nationalid/IRN.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import re
2+
from types import SimpleNamespace
3+
from typing import Optional
4+
from .util import CHECK_DIGIT, validate_regexp, weighted_modulus_digit, letter_to_number
5+
6+
7+
def normalize(id_number: str) -> str:
8+
"""strip out useless characters/whitespaces"""
9+
return id_number.replace('-', '')
10+
11+
12+
class NationalID:
13+
"""
14+
Iran national id number, (کارت ملی/kart-e-meli)
15+
https://en.wikipedia.org/wiki/National_identification_number#Iran,_Islamic_Republic_of
16+
"""
17+
METADATA = SimpleNamespace(**{
18+
'iso3166_alpha2': 'IR',
19+
'min_length': 10,
20+
'max_length': 10,
21+
'parsable': False,
22+
'checksum': True,
23+
'regexp': re.compile(r'^\d{3}-?\d{6}-?\d$')
24+
})
25+
26+
MULTIPLIER = [10, 9, 8, 7, 6, 5, 4, 3, 2]
27+
28+
@staticmethod
29+
def validate(id_number: str) -> bool:
30+
"""
31+
Validate
32+
"""
33+
if not validate_regexp(id_number, NationalID.METADATA.regexp):
34+
return False
35+
return NationalID.checksum(id_number) == int(id_number[-1])
36+
37+
@staticmethod
38+
def checksum(id_number: str) -> Optional[CHECK_DIGIT]:
39+
"""algorithm: https://github.com/mohammadv184/idvalidator/blob/main/validate/nationalid/nationalid.go"""
40+
normalized = normalize(id_number)
41+
numbers = [int(i) for i in normalized]
42+
modulus = weighted_modulus_digit(numbers[:-1], NationalID.MULTIPLIER, 11, True)
43+
return modulus if modulus < 2 else 11 - modulus

tests/nationalid/test_IRN.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from unittest import TestCase
2+
from idnumbers.nationalid import IRN
3+
4+
5+
class TestIRNValidation(TestCase):
6+
def test_normal_case(self):
7+
self.assertTrue(IRN.NationalID.validate('472-171992-2'))
8+
self.assertTrue(IRN.NationalID.validate('4608968882'))
9+
self.assertTrue(IRN.NationalID.validate('1111111111'))
10+
self.assertTrue(IRN.NationalID.validate('0939092001'))
11+
12+
def test_error_case(self):
13+
self.assertFalse(IRN.NationalID.validate('472-171992-1'))
14+
self.assertFalse(IRN.NationalID.validate('2130396217'))
15+
self.assertFalse(IRN.NationalID.validate('0000000001'))
16+
self.assertFalse(IRN.NationalID.validate('abcd1234'))

0 commit comments

Comments
 (0)