Validator, generator and parser for Bulgarian unique citizenship numbers (EGN/ЕГН).
Project description
egn
A Python library and command-line tool for validating, parsing and generating the Bulgarian Unified Civil Number (ЕГН / EGN — Единен граждански номер).
Библиотека и команден ред на Python за проверка, анализ и генериране на български Единни граждански номера (ЕГН).
Table of contents / Съдържание
- What is an EGN?
- Installation / Инсталация
- Python API
- Command-line interface / Команден ред
- Regions / Области
- Algorithm / Алгоритъм
- Development / Разработка
- License / Лиценз
What is an EGN? / Какво е ЕГН?
English. The EGN (Unified Civil Number) is a 10-digit identifier assigned to every Bulgarian citizen and to every foreign resident. It encodes:
| Positions | Meaning |
|---|---|
| 1–2 | Year of birth (last two digits) |
| 3–4 | Month of birth, with a century offset: +20 for births in the 1800s, +40 for births after 2000 |
| 5–6 | Day of birth |
| 7–9 | Regional code (0 – 999), assigned by the civil registry and reflecting the place of registration |
| 9 | The last digit of the regional code also encodes the sex: even = male, odd = female |
| 10 | Check digit (mod-11 / mod-10 weighted checksum) |
Български. ЕГН-то е 10-цифрен идентификатор, съдържащ датата на
раждане, район на регистрация, пол и контролна цифра. Месецът е
кодиран с добавени +20 за рождени през XIX век и +40 за рождени
след 2000 г. Полът се определя от последната цифра на кода на
областта: четна → мъж, нечетна → жена.
Note / Забележка. Dates between 1 April 1916 and 13 April 1916 do not exist — Bulgaria adopted the Gregorian calendar by skipping those 13 days. EGNs carrying such dates are considered invalid by this library.
Installation / Инсталация
pip install egn
Supported Python: 3.6+ (the library uses f-strings).
Python API
import egn
validate(egn)
Return True if egn is a valid EGN, False otherwise.
Accepts either a str or an int (ints are zero-padded to 10 digits).
Връща True, ако ЕГН-то е валидно.
>>> egn.validate('0021010899')
True
>>> egn.validate(21010899) # int, will be zero-padded
True
>>> egn.validate('1234567890')
False
parse(egn)
Return a dict describing the EGN. Raises Exception('Invalid EGN')
if the input is invalid.
Връща речник с данните, извлечени от ЕГН-то.
>>> egn.parse('1111136273')
{
'year': 1911,
'month': 11,
'day': 13,
'datetime': datetime.datetime(1911, 11, 13, 0, 0),
'region_bg': 'София',
'region_en': 'Sofia',
'region_iso': 'BG-22',
'gender': 'Female',
'egn': '1111136273',
}
get_date(egn)
Return just the date portion of an EGN (decoded year, month, day
and a datetime). Returns False for malformed input.
>>> egn.get_date('9941011142')
{'year': 2099, 'month': 1, 'day': 1, 'datetime': datetime.datetime(2099, 1, 1, 0, 0)}
generate(date_from, date_to, gender, region, limit)
Deterministically enumerate valid EGNs matching the given constraints. All parameters are optional and can be mixed freely.
Генерира всички валидни ЕГН-та, които отговарят на зададените филтри. Всички параметри са по избор и могат да се комбинират.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
date_from |
str (YYYY-MM-DD) |
'1800-01-01' |
Earliest date of birth to enumerate. |
date_to |
str (YYYY-MM-DD) |
today | Latest date of birth to enumerate. |
gender |
'm' / 'male' / 'f'/ 'female' |
None |
Filter by sex. None returns both. |
region |
str |
None |
Region name in Latin, Cyrillic or ISO 3166-2 (e.g. 'Sofia', 'София', 'BG-22'). None returns every region. |
limit |
int / None |
10 |
Maximum number of EGNs to return. Pass None to enumerate every combination. |
Examples:
# All EGNs for men born in Sofia on 2020-10-15.
egn.generate(region='Sofia', gender='m',
date_from='2020-10-15', date_to='2020-10-15',
limit=None)
# -> 49 EGNs (one per even region code in 624-721)
# All female EGNs in Burgas across January 2020.
egn.generate(region='Burgas', gender='f',
date_from='2020-01-01', date_to='2020-01-31',
limit=None)
# Every EGN for a single day regardless of region or gender.
egn.generate(date_from='1999-12-31', date_to='1999-12-31', limit=None)
# -> 1000 EGNs (one per region code 000-999)
# Using Cyrillic or ISO region names.
egn.generate(region='Пловдив', limit=5)
egn.generate(region='BG-16', limit=5)
How partial inputs compose:
date_from/date_to |
gender |
region |
limit |
Result |
|---|---|---|---|---|
| date range | any | any | N |
First N EGNs in the range, all regions, both sexes |
| single day | 'm' |
any | None |
Every male EGN born that day, across all regions |
| date range | any | 'Varna' |
None |
Every EGN born in Varna during the range |
| date range | 'f' |
'BG-22' |
None |
Every female EGN born in Sofia in the range |
generate_random(gender, region, limit)
Return limit random valid EGNs. Each EGN has a uniformly random date
between 1800-01-01 and yesterday and a uniformly random region (or the
one you specified).
Генерира произволни ЕГН-та.
>>> egn.generate_random(limit=3, region='Varna', gender='f')
['8841020217', '2643026019', '5424077115']
Command-line interface / Команден ред
After installation the egn command is available:
# Validate
$ egn -v 0021010899
0021010899 is valid!
# Parse (prints JSON)
$ egn -p 9941011142
{"year": 2099, "month": 1, "day": 1, "region_bg": "Варна", ...}
# Generate with full filter set
$ egn -g --from 2020-10-15 --to 2020-10-15 --region Sofia --gender m
# -> prints 49 EGNs, one per line
# Generate — omit --limit to enumerate every combination
$ egn -g --from 2020-01-01 --to 2020-01-01 --region Pernik
# -> prints all 18 EGNs for that day and region
# Generate with a cap
$ egn -g --from 2020-01-01 --to 2020-12-31 --region Burgas --limit 100
# Random EGNs
$ egn -r --limit 5
$ egn -r --region Пловдив --gender f --limit 3
Flags:
| Flag | Purpose |
|---|---|
-v EGN |
Validate a single EGN. |
-p EGN |
Parse a single EGN and print JSON. |
-g |
Generate EGNs matching the given filters. |
-r |
Generate random EGNs. |
-l N / --limit N |
Cap the number of results. Omit with -g to enumerate every combination. |
--gender m/f |
Filter by sex. |
--region NAME |
Latin, Cyrillic, or ISO 3166-2 region name. |
--from DATE |
ISO date YYYY-MM-DD. Default 1800-01-01. |
--to DATE |
ISO date YYYY-MM-DD. Default: today. |
Regions / Области
The regional code in positions 7–9 of the EGN maps to one of 29 administrative regions. The library ships with the full table, keyed by ISO 3166-2 code, Bulgarian name, and English transliteration.
Библиотеката съдържа пълната таблица на 29-те области, като търсенето работи с латиница, кирилица или ISO 3166-2 код.
| ISO | English | Български | Code range |
|---|---|---|---|
| BG-01 | Blagoevgrad | Благоевград | 000–043 |
| BG-02 | Burgas | Бургас | 044–093 |
| BG-03 | Varna | Варна | 094–139 |
| BG-04 | Veliko Turnovo | Велико Търново | 140–169 |
| BG-05 | Vidin | Видин | 170–183 |
| BG-06 | Vratza | Враца | 184–217 |
| BG-07 | Gabrovo | Габрово | 218–233 |
| BG-08 | Dobrich | Добрич | 790–821 |
| BG-09 | Kurdzhali | Кърджали | 234–281 |
| BG-10 | Kyustendil | Кюстендил | 282–301 |
| BG-11 | Lovech | Ловеч | 302–319 |
| BG-12 | Montana | Монтана | 320–341 |
| BG-13 | Pazardzhik | Пазарджик | 342–377 |
| BG-14 | Pernik | Перник | 378–395 |
| BG-15 | Pleven | Плевен | 396–435 |
| BG-16 | Plovdiv | Пловдив | 436–501 |
| BG-17 | Razgrad | Разград | 502–527 |
| BG-18 | Ruse | Русе | 528–555 |
| BG-19 | Silistra | Силистра | 556–575 |
| BG-20 | Sliven | Сливен | 576–601 |
| BG-21 | Smolyan | Смолян | 602–623 |
| BG-22 | Sofia | София | 624–721 |
| BG-23 | Sofia (county) | София (окръг) | 722–751 |
| BG-24 | Stara Zagora | Стара Загора | 752–789 |
| BG-25 | Targovishte | Търговище | 822–843 |
| BG-26 | Haskovo | Хасково | 844–871 |
| BG-27 | Shumen | Шумен | 872–903 |
| BG-28 | Yambol | Ямбол | 904–925 |
| BG-XX | Other | Друг | 926–999 |
Algorithm / Алгоритъм
The checksum in position 10 is computed from the first 9 digits using
the weights (2, 4, 8, 5, 10, 9, 7, 3, 6):
checksum = (sum(weight_i * digit_i for i in 1..9) mod 11) mod 10
If that value equals the 10th digit, the EGN is well-formed. The library additionally verifies that positions 1–6 decode to a real calendar date, that the date is not inside the 1–13 April 1916 Gregorian gap, and that the regional code is in range.
Reference: http://www.grao.bg/esgraon.html#section2
Development / Разработка
git clone https://github.com/miglen/egn.git
cd egn
python3 -m venv .venv && source .venv/bin/activate
pip install -e . pytest
pytest test/
Contributions welcome. Please include a test case with any bug fix or new feature.
Приноси са добре дошли. Моля, добавяйте тест за всяка корекция или нова възможност.
License / Лиценз
GNU General Public License v3.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file egn-0.1.5.tar.gz.
File metadata
- Download URL: egn-0.1.5.tar.gz
- Upload date:
- Size: 34.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4f53c840d73390b36c6de5da883aa4abb2873b871a7a4518ab83834f0fd5580
|
|
| MD5 |
87f4bed329c0d22705195e837feccf4a
|
|
| BLAKE2b-256 |
341840e3459475d926c88b9c69c5f69ca72176eeda627ff14323a655314207e4
|
File details
Details for the file egn-0.1.5-py2.py3-none-any.whl.
File metadata
- Download URL: egn-0.1.5-py2.py3-none-any.whl
- Upload date:
- Size: 31.3 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
173faa518d9222661e6e5155140d91398885f97120678471404b855ecf5278e8
|
|
| MD5 |
ecb54e645a6bda604a468f2c4aaf7ebf
|
|
| BLAKE2b-256 |
fc20e757705afa9297cc82f836c2d55182b1a3bf27a52c3615fba757dd2afa9f
|