import os
from typing import Union
from datetime import date, datetime
import pandas as pd
this_dir, this_filename = os.path.split(__file__)
[docs]
DATA_PATH = os.path.join(this_dir, "data", "regcode.csv")
[docs]
rc = pd.read_csv(DATA_PATH)
[docs]
def _check_length(idnum: Union[str, int]) -> str:
idnum = str(idnum)
if len(idnum) == 16:
return idnum
elif len(idnum) < 16:
raise ValueError(f'Identification number (NIK) is too short ({len(idnum)} characters), length should be 16')
elif len(idnum) > 16:
raise ValueError(f'Identification number (NIK) is too long ({len(idnum)} characters), length should be 16')
else:
raise ValueError(f'Identification number (NIK) {len(idnum)} characters, length should be 16')
[docs]
def _check_birth(idnum: str):
bcode = idnum[6:12]
if int(bcode[:2]) > 31:
bcode = bcode.replace(bcode[:2], str(int(bcode[:2]) - 40).zfill(2), 1)
try:
bdtm = datetime.strptime(bcode, "%d%m%y")
now = datetime.now()
if bdtm > now:
bdtm = bdtm.replace(year = bdtm.year - 100)
except:
# return NaN if birth date is invalid
bdtm = float('nan')
return bdtm
[docs]
def province(idnum: Union[str, int]):
idnum = _check_length(idnum)
prov_code = int(idnum[:2])
try:
prov = rc.loc[rc['code'] == prov_code, 'region'].item()
except:
prov = float('nan')
return prov
[docs]
def city(idnum: Union[str, int]):
idnum = _check_length(idnum)
city_code = int(idnum[:4])
try:
city = rc.loc[rc['code'] == city_code, 'region'].item()
except:
city = float('nan')
return city
[docs]
def district(idnum: Union[str, int]):
idnum = _check_length(idnum)
dist_code = int(idnum[:6])
try:
dist = rc.loc[rc['code'] == dist_code, 'region'].item()
except:
dist = float('nan')
return dist
[docs]
def gender(idnum: Union[str, int]) -> str:
idnum = _check_length(idnum)
gend_code = int(idnum[6:8])
if gend_code >= 1 and gend_code <= 31:
gend = "Male"
elif gend_code >= 41 and gend_code <= 71:
gend = "Female"
else:
raise ValueError("Identification number (NIK) invalid, character[6:8] must be between 1 to 71")
return gend
[docs]
def birthdate(idnum: Union[str, int]):
idnum = _check_length(idnum)
bdtm = _check_birth(idnum)
try:
bdate = bdtm.day
except:
bdate = float('nan')
return bdate
[docs]
def birthmonth(idnum: Union[str, int]):
idnum = _check_length(idnum)
bdtm = _check_birth(idnum)
try:
bmonth = bdtm.month
except:
bmonth = float('nan')
return bmonth
[docs]
def birthyear(idnum: Union[str, int]):
idnum = _check_length(idnum)
bdtm = _check_birth(idnum)
try:
byear = bdtm.year
except:
byear = float('nan')
return byear
[docs]
def birthdtm(idnum: Union[str, int]): # birthday in datetime data type
idnum = _check_length(idnum)
bdtm = _check_birth(idnum)
return bdtm
[docs]
def birthday(idnum: Union[str, int]): # birthday in string data type
idnum = _check_length(idnum)
bdtm = _check_birth(idnum)
try:
bday = bdtm.strftime("%d %B %Y")
except:
bday = float('nan')
return bday
[docs]
def age(idnum: Union[str, int]):
idnum = _check_length(idnum)
bdtm = _check_birth(idnum)
today = date.today()
try:
age = today.year - bdtm.year - ((today.month, today.day) < (bdtm.month, bdtm.day))
except:
age = float('nan')
return age
[docs]
def nth_person(idnum: Union[str, int]):
idnum = _check_length(idnum)
nth = int(idnum[13:])
return nth
[docs]
def all_info(idnum: Union[str, int]) -> dict:
idnum = _check_length(idnum)
nik_dict = {'NIK': int(idnum), 'province': province(idnum), 'city': city(idnum), 'district': district(idnum),
'gender': gender(idnum), 'birth_datetime': birthdtm(idnum), 'birthday': birthday(idnum),
'age': age(idnum), 'regist_code': nth_person(idnum)}
return nik_dict