# egypt-nid
**egypt-nid** is the definitive Python library for parsing, validating, and extracting structured data from Egyptian National ID numbers (الرقم القومي).
---
## Features
- ✅ Full 14-digit structural validation (century, birth date, governorate, Luhn checksum)
- 🔒 Strict mode (raises typed exceptions) and lenient mode (collects warnings)
- 📊 Bulk parsing, filtering, and aggregate statistics
- 🌍 Governorate names in English and Arabic with locale support
- 🎭 Masking for safe display
- 🖥️ CLI tool (`egypt-nid`)
- 🔌 Framework-ready (Django, FastAPI, Pandas — no hard dependencies)
- 📦 `py.typed` – PEP 561 compliant, fully typed
- ⚡ LRU-cached repeated parses
---
## Installation
```bash
pip install egypt-nid
```
## Quick Start
```python
from egypt_nid import parse
nid = parse("30105150123456")
print(nid.birth_date) # datetime.date(2001, 5, 15)
print(nid.age) # 23 (depends on current date)
print(nid.gender) # 'male'
print(nid.governorate_name) # 'Cairo'
print(nid.governorate_name_ar) # 'القاهرة'
print(nid.is_adult()) # True
print(nid.born_outside_egypt) # False
print(nid.masked()) # '3** ** ** **** 3456'
```
## Error Handling
### Strict mode (default)
```python
from egypt_nid import parse
from egypt_nid.exceptions import (
LengthError, NonNumericError, CenturyError,
BirthDateError, GovernorateError, ChecksumError,
)
try:
nid = parse("bad_input")
except LengthError as e:
print(f"Wrong length: {e}")
except ChecksumError as e:
print(f"Typo detected: {e}")
except EgyptNIDError as e:
print(f"Validation failed: {e}")
```
### Lenient mode
```python
from egypt_nid import parse_lenient
nid, result = parse_lenient("30105150123457") # bad checksum
if not result.valid:
for field, warning in result.warnings.items():
print(f" [{field}] {warning}")
# nid is still returned if only non-critical checks fail
```
## Serialisation
```python
nid = parse("30105150123456")
# Dictionary
d = nid.t …