A Python library for validating and parsing Serbian unique master citizen numbers (JMBG - Jedinstveni Matični Broj Građana).
- ✅ Validate JMBG numbers with comprehensive checks
- ✅ Extract birth date, region, and gender information
- ✅ Support for all Serbian regions
- ✅ Calculate age from JMBG
- ✅ Type-safe with Python type hints
- ✅ Fully tested with unittest
- ✅ No external dependencies
Install via pip:
pip install jmbg-labsOr clone the repository:
git clone https://github.com/jmbg-labs/python.git
cd pythonfrom jmbg import Jmbg, valid
# Quick validation
if valid('0101000710009'):
print("Valid JMBG")
# Parse and validate
try:
jmbg = Jmbg.parse('0101000710009')
print(f"Valid JMBG: {jmbg.format()}")
except JmbgError as e:
print(f"Invalid JMBG: {e}")from jmbg import Jmbg
jmbg = Jmbg('0101000710009')
# Get birth date
date = jmbg.get_date() # datetime.date object
print(date.strftime('%Y-%m-%d')) # 2000-01-01
# Get age
print(jmbg.get_age()) # e.g., 26
# Check gender
if jmbg.is_male():
print("Male")
if jmbg.is_female():
print("Female")
# Access individual parts
print(jmbg.day) # 1
print(jmbg.month) # 1
print(jmbg.year) # 2000
print(jmbg.region) # 71
print(jmbg.region_text) # "Belgrade"
print(jmbg.country) # "Serbia"
print(jmbg.unique) # 0
print(jmbg.checksum) # 9jmbg = Jmbg('1505995800002')
# String conversion
print(str(jmbg)) # "1505995800002"
print(jmbg.format()) # "1505995800002"
# Property access
print(jmbg.original) # "1505995800002"
print(jmbg.day_original) # "15"
print(jmbg.month_original) # "05"
print(jmbg.year_original) # "995"
print(jmbg.region_original) # "80"
print(jmbg.unique_original) # "000"
# Check adult status
if jmbg.is_adult():
print("Adult (18+)")JMBG consists of 13 digits: DDMMYYYRRBBBC
- DD - Day of birth (01-31)
- MM - Month of birth (01-12)
- YYY - Year of birth (last 3 digits)
- RR - Region code
- BBB - Unique number (000-499 for males, 500-999 for females)
- C - Checksum digit
The library supports all Serbian and ex-Yugoslav regions including (beware: ex-Yugoslav regions codes may have changed since the breakup):
- Serbia (71-79): Belgrade, Kragujevac, Niš, etc.
- Serbia/Vojvodina (80-89): Novi Sad, Subotica, Pančevo, etc.
- Serbia/Kosovo (91-96): Priština, Peć, Prizren, etc.
- Bosnia and Herzegovina (10-19)
- Montenegro (21-29)
- Croatia (30-39)
- Macedonia (41-49)
- Slovenia (50)
The library performs comprehensive validation:
- Length check - Must be exactly 13 digits
- Format check - Must contain only numeric characters
- Date validation - Birth date must be valid (including leap year support)
- Region validation - Region code must exist in the registry
- Checksum validation - Modulo 11 algorithm verification
# Run all tests
python -m unittest discover
# Run specific test file
python -m unittest test_jmbg
# Run tests with verbose output
python -m unittest test_jmbg -v# Format code with black
black .
# Check types with mypy
mypy jmbg.py- Python ^3.8
- No external dependencies (for production use)
Contributions are welcome! Please ensure:
- All tests pass (
python -m unittest discover) - Code follows PEP 8 standards
- Add tests for new features
- Update documentation as needed
This project is licensed under the MIT License - see the LICENSE file for details.
Developed by JMBG Labs
from jmbg import Jmbg, valid
jmbgs = ['0710003730015', '1705978730032', 'invalid']
for jmbg_string in jmbgs:
if valid(jmbg_string):
jmbg = Jmbg.parse(jmbg_string)
print(f"{jmbg.format()} - Born: {jmbg.get_date()}, "
f"Region: {jmbg.region_text}, "
f"Gender: {'Male' if jmbg.is_male() else 'Female'}")
else:
print(f"{jmbg_string} - Invalid")from jmbg import Jmbg
jmbg = Jmbg('0710003730015')
age = jmbg.get_age()
if age >= 18:
print("Adult")
else:
print("Minor")from jmbg import Jmbg
from jmbg_error import JmbgError
try:
jmbg = Jmbg('1234567890123')
except JmbgError as e:
# Handle specific validation errors
print(f"Validation failed: {e}")
# Possible messages:
# - "JMBG string must have exactly 13 digits, got X"
# - "JMBG must contain only numeric characters"
# - "Date 'DD/MM/YYYY' is not valid"
# - "Region 'XX' is not valid for JMBG"
# - "Checksum is not valid"from jmbg import Jmbg
from gender import Gender
jmbg = Jmbg('0710003730015')
# Get gender enum
gender = jmbg.gender()
if gender == Gender.MALE:
print("Male")
elif gender == Gender.FEMALE:
print("Female")
# Or use convenience methods
print(jmbg.is_male()) # True
print(jmbg.is_female()) # Falsefrom jmbg import Jmbg
import datetime
jmbg = Jmbg('2902992710005') # Leap year date
birth_date = jmbg.get_date()
# Calculate days until next birthday
today = datetime.date.today()
next_birthday = datetime.date(today.year, birth_date.month, birth_date.day)
if next_birthday < today:
next_birthday = datetime.date(today.year + 1, birth_date.month, birth_date.day)
days_until = (next_birthday - today).days
print(f"Days until birthday: {days_until}")