def check_150_years_age(individual_info_dict): age_limit = 150 # gets dates from individual info for individual_id, individual_info in individual_info_dict.items(): id = individual_id birth_date = Date(str(individual_info.get("BIRT"))) if individual_info.get("DEAT") not in [None, 'NA']: death_date = Date(str(individual_info.get("DEAT"))) else: death_date = None # calculates age with the dates if death_date == None and birth_date != None: age = Date.get_dates_difference(birth_date.date_time_obj) else: if death_date != None and birth_date != None: age = Date.get_dates_difference(birth_date.date_time_obj, death_date.date_time_obj) # checks to see if age exceeds age limit and prints error if type(age) is not str and age > age_limit and death_date == None: print( 'ERROR: INDIVIDUAL: US07: {}: More than 150 years old - Birth date {}' .format(id, birth_date)) elif type(age) is not str and age > age_limit and death_date != None: print( 'ERROR: INDIVIDUAL: US07: {}: More than 150 years old at death - Birth date {}: Death date {}' .format(id, birth_date, death_date))
def check_birth_before_marriage_of_parents(family_info_dict, individual_info_dict): for family_id, family_info in family_info_dict.items(): # gets marriage and divorce dates in family if they exist if family_info.get("MARR") not in [None, 'NA']: marriage_date = Date(str(family_info.get("MARR"))) else: marriage_date = None if family_info.get("DIV") not in [None, 'NA']: divorce_date = Date(str(family_info.get("DIV"))) else: divorce_date = None # obtains all childen in family children = family_info.get('CHIL') #if children exist, it gets the birth dates and compares it to the marriage/divorce dates, and prints error if marriage is before birth and/or birth is after divorce if children not in [None, 'NA']: for child in children: child_dict = individual_info_dict.get(child) birth_date = Date(str(child_dict.get('BIRT'))) if type(marriage_date) is not str and marriage_date != None and type(marriage_date.date_time_obj) is not str and type(birth_date.date_time_obj) is not str: if marriage_date not in [None, 'NA'] and marriage_date.date_time_obj < birth_date.date_time_obj: print('ANOMOLY: FAMILY: US08: {}: Child {} born {} before marriage on {}'.format(family_id, child, birth_date, marriage_date)) if type(divorce_date) is not str and divorce_date != None and type(divorce_date.date_time_obj) is not str and type(birth_date.date_time_obj) is not str: if divorce_date not in [None, 'NA'] and birth_date.date_time_obj > divorce_date.date_time_obj: print('ANOMOLY: FAMILY: US08: {}: Child {} born {} after divorce on {}'.format(family_id, child, birth_date, divorce_date))
def test_us04(self): """ Test for US04 """ # Test with GEDCOM individual @I4@ husb_id = '@I4@' wife_id = '@I6@' marriage_dt = Date('18 Jun 2019') divorce_dt = Date('18 Jun 2018') fam_id = '@F3@' error_chk = True self.assertEqual( us04(husb_id, wife_id, marriage_dt, divorce_dt, fam_id, True), error_chk) return None
def list_upcoming_birthdays(individual_info_dict, use_todays_date=True): """ Lists all birthdays within a month in a GEDCOM file. """ upcoming_birthday_list = [] if use_todays_date == True: today = datetime.date.today() else: today = datetime.date(2019, 6, 1) for individual_id, individual_info in individual_info_dict.items(): id = individual_id name = individual_info.get('NAME') birth_date = Date(str(individual_info.get("BIRT"))).date_time_obj if birth_date not in [None, 'NA', '']: this_year_birthday = datetime.date(today.year, birth_date.month, birth_date.day) difference = this_year_birthday - today if difference > datetime.timedelta(0) and difference < datetime.timedelta(30): info = [id, name] upcoming_birthday_list.append(info) pt = '' if len(upcoming_birthday_list) > 0: pt = PrettyTable(field_names=["ID", "Name"]) for id, name in upcoming_birthday_list: mults_info_list = [id, name] pt.add_row(mults_info_list) if pt != '': return_print = "US38: List: The following individuals have upcoming birthdays within 30 days!\n" + str(pt) else: return_print = None return return_print
def test_us05(self): """ Test for US05 """ # Test with GEDCOM individual @I6@ husb_id = '@I4@' wife_id = '@I6@' husb_death_dt = Date('18 Jun 2020') wife_death_dt = Date('18 Jun 2017') marriage_dt = Date('18 Jun 2019') fam_id = '@F3@' error_chk = [False, True] self.assertEqual( us05(husb_id, husb_death_dt, wife_id, wife_death_dt, marriage_dt, fam_id, True), error_chk) return None
def test_us02_us10(self): """ Test for US02 and US10 """ # Test with GEDCOM individual @I4@ husb_id = '@I4@' wife_id = '@I6@' husb_birth_dt = Date('18 Jun 2021') wife_birth_dt = Date('18 Jun 2000') marriage_dt = Date('18 Jun 2019') fam_id = '@F3@' error_chk = [True, False, True, False] # Must add functionality of Date Class prior to sending dates to US02 self.assertEqual( us02(husb_id, husb_birth_dt, wife_id, wife_birth_dt, marriage_dt, fam_id, True), error_chk) return None
def check_bigamy(individual_info_dict, family_info_dict): for individual_id, individual_info in individual_info_dict.items(): id = individual_id name_place = individual_info.get('NAME') name = re.sub('/', '', name_place) marriage_count = 0 start_dates = [] end_dates = [] for family_id, family_info in family_info_dict.items(): wife_id = family_info.get('WIFE') husband_id = family_info.get('HUSB') if id == wife_id or id == husband_id: if id == wife_id: spouse_death = individual_info_dict[husband_id].get('DEAT') # print(family_info.get('MARR')) # print(spouse_death) elif id == husband_id: spouse_death = individual_info_dict[wife_id].get('DEAT') # print(family_info.get('MARR')) # print(spouse_death) Range = namedtuple('Range', ['start', 'end']) if family_info.get('DIV') not in [None, 'NA']: length_of_marriage = Range(start=family_info.get('MARR'), end=family_info.get('DIV')) elif spouse_death not in [None, 'NA']: length_of_marriage = Range(start=family_info.get('MARR'), end=spouse_death) else: length_of_marriage = Range(start=family_info.get('MARR'), end=Date(datetime.datetime.today().strftime('%d %b %Y'))) if family_info.get('MARR') not in [None, 'NA']: start_dates.append(length_of_marriage.start.date_time_obj) end_dates.append(length_of_marriage.end.date_time_obj) marriage_count += 1 more_than_one_marriage_at_given_time = False if marriage_count > 1: latest_start = max(start_dates) earliest_end = min(end_dates) if type(latest_start) is not str and latest_start != None: if type(earliest_end) is not str and earliest_end != None: delta = (earliest_end - latest_start).days overlap = max(0, delta) if overlap > 0: more_than_one_marriage_at_given_time = True if more_than_one_marriage_at_given_time == True: print('ANOMOLY: INDIVIDUAL: US11: {}: Bigamy detected: {} married to multiple spouses at the same time'.format(id, name))
def check_parents_not_too_old(individual_info_dict, family_info_dict): for family_id, family_info in family_info_dict.items(): wife_id = family_info.get('WIFE') husband_id = family_info.get('HUSB') children = family_info.get('CHIL') husb_dict = individual_info_dict.get(husband_id) wife_dict = individual_info_dict.get(wife_id) husb_birth_date = Date(str(husb_dict.get('BIRT'))) wife_birth_date = Date(str(wife_dict.get('BIRT'))) parents_too_old = False if children not in [None, 'NA']: for child in children: child_dict = individual_info_dict.get(child) birth_date = Date(str(child_dict.get('BIRT'))) too_old_age_difference = 65 if type(husb_birth_date) is not str and husb_birth_date != None and type(husb_birth_date.date_time_obj) is not str and type(husb_birth_date.date_time_obj) is not str: if type(wife_birth_date) is not str and wife_birth_date != None and type(wife_birth_date.date_time_obj) is not str and type(wife_birth_date.date_time_obj) is not str: if type(birth_date) is not str and birth_date != None and type(birth_date.date_time_obj) is not str and type(birth_date.date_time_obj) is not str: if Date.get_dates_difference(husb_birth_date.date_time_obj, birth_date.date_time_obj) > too_old_age_difference or Date.get_dates_difference(wife_birth_date.date_time_obj, birth_date.date_time_obj) > too_old_age_difference: parents_too_old = True if parents_too_old == True: print('ANOMOLY: FAMILY: US12: {}: Parents are too old: Parent(s) were greater than 65 years old when child was born'.format(family_id))
def list_upcoming_anniversaries(individual_info_dict, family_info_dict, use_todays_date=True): """ Lists all anniversaries that occur within a month in a GEDCOM file. """ upcoming_anniversary_list = [] if use_todays_date == True: today = datetime.date.today() else: today = datetime.date(2019, 6, 1) pt = '' for family_id, family_info in family_info_dict.items(): wife_id = family_info.get('WIFE') husband_id = family_info.get('HUSB') wife_name = '' husb_name = '' for individual_id, individual_info in individual_info_dict.items(): if individual_id == wife_id: wife_name = individual_info.get('NAME') elif individual_id == husband_id: husb_name = individual_info.get('NAME') wedding_date = Date(str(family_info.get("MARR"))).date_time_obj if wedding_date not in [None, 'NA', '']: this_year_anniversary = datetime.date(today.year, wedding_date.month, wedding_date.day) difference = this_year_anniversary - today if difference > datetime.timedelta(0) and difference < datetime.timedelta(30): info = [wife_id, wife_name, husband_id, husb_name] upcoming_anniversary_list.append(info) pt = '' if len(upcoming_anniversary_list) > 0: pt = PrettyTable(field_names=["Wife ID", "Wife Name", "Husband ID", "Husband Name"]) for info in upcoming_anniversary_list: pt.add_row(info) if pt != '': return_print = "US39: List: The following couples have upcoming anniversaries within 30 days!\n" + str(pt) else: return_print = None return return_print
def gedcom_file_parser(path, return_duplicate_ids = False): """gedcom file parser opens and reads a gedcom file line-byline and stores the fields of individuals and families in separate dictionaries. The key of individuals dictionary is the individual id, for families dictionary it is family id. Arguments: path {string} -- this is the path of the gedcom file Returns: {tuple of dictionaries} -- the return value is a tuple of individuals and families dictionary """ try: fp = open(path, "r") except FileNotFoundError: print("Can't open", path) else: duplicate_ids = [] with fp: line = fp.readline() individuals_dict = dict() family_dict = dict() while line: if line != "": tag_array = LEVEL_TAGS.get(line[0]) line_split = line.split() if tag_array == None: line = fp.readline() continue elif line_split[0] == "0": if len(line_split) > 2 and line_split[2] == "INDI": individual_id = line_split[1] if individuals_dict.get(individual_id) != None: duplicate_ids.append(individual_id) line = fp.readline() continue individuals_dict[individual_id] = {} line = fp.readline().rstrip("\n") if line: line_split = line.split() while "INDI" not in line_split: if "FAM" in line_split or not line: break if line_split[1] in get_individual_info_tags(): if line_split[1] == "BIRT": line = fp.readline().rstrip("\n") if line != "": line_split = line.split() if line_split[1] == "DATE": individuals_dict[individual_id]["BIRT"] = Date(" ".join( line_split[2:])) elif line_split[1] == "DEAT": line = fp.readline().rstrip("\n") if line != "": line_split = line.split() if line_split[1] == "DATE": individuals_dict[individual_id]["DEAT"] = Date(" ".join( line_split[2:])) else: individuals_dict[individual_id][line_split[1]] = " ".join( line_split[2:]) line = fp.readline().rstrip("\n") line_split = line.split() else: line = fp.readline().rstrip("\n") line_split = line.split() continue if "FAM" in line_split and len(line_split) > 2: family_id = line_split[1] if family_dict.get(family_id) != None: duplicate_ids.append(family_id) line = fp.readline() continue family_dict[family_id] = {} line = fp.readline().rstrip("\n") line_split = line.split() while "FAM" not in line_split: if line: if line_split[1] in get_family_info_tags(): if line_split[1] == "MARR": line = fp.readline().rstrip("\n") if line: line_split = line.split() if line_split[1] == "DATE": family_dict[family_id]["MARR"] = Date(" ".join( line_split[2:])) elif line_split[1] == "DIV": line = fp.readline().rstrip("\n") if line: line_split = line.split() if line_split[1] == "DATE": family_dict[family_id]["DIV"] = Date(" ".join( line_split[2:])) elif line_split[1] == "CHIL": if family_dict[family_id].get("CHIL") == None: family_dict[family_id]["CHIL"] = [ line_split[2]] else: family_dict[family_id]["CHIL"].append( line_split[2]) else: family_dict[family_id][line_split[1]] = " ".join( line_split[2:]) line = fp.readline().rstrip("\n") line_split = line.split() else: line = fp.readline().rstrip("\n") line_split = line.split() continue else: break else: if "INDI" not in line_split: line = fp.readline().rstrip("\n") continue else: line = fp.readline().rstrip("\n") continue if return_duplicate_ids: return individuals_dict, family_dict, duplicate_ids else: return individuals_dict, family_dict