diff --git a/ChangeLog b/ChangeLog index 8bbf6fef8..7a76769dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-11-21 Douglas S. Blank + * src/Utils.py: probably_alive now takes date rather than year + * src/gen/proxy/living.py: create date from year + * src/gen/lib/date.py: added methods to do date math + and return Date object (set_yr_mon_day_offset, copy_offset_ymd) + * src/plugins/Calendar.py: updated to use probably alive date + * src/Filters/Rules/Person/_ProbablyAlive.py: parse entry as date + 2007-11-20 Jerome Rapinat * src/plugins/Makefile.am: up to date diff --git a/src/Filters/Rules/Person/_ProbablyAlive.py b/src/Filters/Rules/Person/_ProbablyAlive.py index 855dab517..e25ddab45 100644 --- a/src/Filters/Rules/Person/_ProbablyAlive.py +++ b/src/Filters/Rules/Person/_ProbablyAlive.py @@ -34,6 +34,7 @@ from gettext import gettext as _ #------------------------------------------------------------------------- from Utils import probably_alive from Filters.Rules._Rule import Rule +import DateHandler #------------------------------------------------------------------------- # "People probably alive" @@ -41,16 +42,16 @@ from Filters.Rules._Rule import Rule class ProbablyAlive(Rule): """People probably alive""" - labels = [_("On year:")] + labels = [_("On date:")] name = _('People probably alive') description = _("Matches people without indications of death that are not too old") category = _('General filters') def prepare(self,db): try: - self.current_year = int(self.list[0]) + self.current_date = DateHandler.parser.parse(unicode(self.list[0])) except: - self.current_year = None + self.current_date = None def apply(self,db,person): - return probably_alive(person,db,self.current_year) + return probably_alive(person,db,self.current_date) diff --git a/src/Utils.py b/src/Utils.py index b1bcc0289..e3ceaa8cb 100644 --- a/src/Utils.py +++ b/src/Utils.py @@ -556,28 +556,39 @@ def create_id(): return "%08x%08x" % ( int(time.time()*10000), rand.randint(0, sys.maxint)) -def probably_alive(person, db, current_year=None, limit=0): - """Returns true if the person may be alive. +#------------------------------------------------------------------------- +# +# probably_alive +# +#------------------------------------------------------------------------- +def probably_alive(person, db, current_date=None, limit=0): + """Returns true if the person may be alive on current_date. This works by a process of emlimination. If we can't find a good reason to believe that someone is dead then we assume they must be alive. + current_date - a date object that is not estimated or modified + (defaults to today) + limit - number of years to check beyond death_date """ + if not current_date: + current_date = gen.lib.Date() + # yr, mon, day: + current_date.set_yr_mon_day(*time.localtime(time.time())[0:3]) + if (current_date.get_quality() == gen.lib.Date.QUAL_ESTIMATED or + current_date.get_modifier() != gen.lib.Date.MOD_NONE): + raise AttributeError, "probably_alive cannot take esitmated or modified dates" - if not current_year: - time_struct = time.localtime(time.time()) - current_year = time_struct[0] - - death_year = None + death_date = None # If the recorded death year is before current year then # things are simple. death_ref = person.get_death_ref() if death_ref and death_ref.get_role() == gen.lib.EventRoleType.PRIMARY: death = db.get_event_from_handle(death_ref.ref) if death.get_date_object().get_start_date() != gen.lib.Date.EMPTY: - death_year = death.get_date_object().get_year() - if death_year + limit < current_year: + death_date = death.get_date_object() + if death_date.copy_offset_ymd(year=limit) < current_date: return False # Look for Cause Of Death, Burial or Cremation events. @@ -587,34 +598,35 @@ def probably_alive(person, db, current_year=None, limit=0): if ev and int(ev.get_type()) in [gen.lib.EventType.CAUSE_DEATH, gen.lib.EventType.BURIAL, gen.lib.EventType.CREMATION]: - if not death_year: - death_year = ev.get_date_object().get_year() + if not death_date: + death_date = ev.get_date_object() if ev.get_date_object().get_start_date() != gen.lib.Date.EMPTY: - if ev.get_date_object().get_year() + limit < current_year: + if (ev.get_date_object().copy_offset_ymd(year=limit) < + current_date): return False # For any other event of this person, check whether it happened # too long ago. If so then the person is likely dead now. - elif ev and too_old(ev.get_date_object(), current_year): + elif ev and too_old(ev.get_date_object(), current_date.get_year()): return False - birth_year = None + birth_date = None # If they were born within 100 years before current year then # assume they are alive (we already know they are not dead). birth_ref = person.get_birth_ref() if birth_ref and birth_ref.get_role() == gen.lib.EventRoleType.PRIMARY: birth = db.get_event_from_handle(birth_ref.ref) if birth.get_date_object().get_start_date() != gen.lib.Date.EMPTY: - if not birth_year: - birth_year = birth.get_date_object().get_year() + if not birth_date: + birth_date = birth.get_date_object() # Check whether the birth event is too old because the # code above did not look at birth, only at other events - if too_old(birth.get_date_object(), current_year): + if too_old(birth.get_date_object(), current_date.get_year()): return False - if not_too_old(birth.get_date_object(), current_year): + if not_too_old(birth.get_date_object(), current_date.get_year()): return True - if not birth_year and death_year: - if death_year > current_year + _MAX_AGE_PROB_ALIVE: + if not birth_date and death_date: + if death_date > current_date.copy_offset_ymd(year=_MAX_AGE_PROB_ALIVE): # person died more than MAX after current year return False @@ -638,10 +650,8 @@ def probably_alive(person, db, current_year=None, limit=0): # if sibling birth date too far away, then not alive: year = dobj.get_year() if year != 0: - if not (current_year - - (_MAX_AGE_PROB_ALIVE + _MAX_SIB_AGE_DIFF) < - year < - current_year + _MAX_SIB_AGE_DIFF): + if not (current_date.copy_offset_ymd(-(_MAX_AGE_PROB_ALIVE + _MAX_SIB_AGE_DIFF)) < + dobj < current_date.copy_offset_ymd(_MAX_SIB_AGE_DIFF)): return False child_death_ref = child.get_death_ref() if child_death_ref: @@ -651,9 +661,8 @@ def probably_alive(person, db, current_year=None, limit=0): # if sibling death date too far away, then not alive: year = dobj.get_year() if year != 0: - if not (current_year - - (_MAX_AGE_PROB_ALIVE + _MAX_SIB_AGE_DIFF) < - year < current_year + _MAX_AGE_PROB_ALIVE): + if not (current_date.copy_offset_ymd(-(_MAX_AGE_PROB_ALIVE + _MAX_SIB_AGE_DIFF)) < + dobj < current_date.copy_offset_ymd(_MAX_AGE_PROB_ALIVE)): return False # Try looking for descendants that were born more than a lifespan @@ -675,7 +684,7 @@ def probably_alive(person, db, current_year=None, limit=0): val = d.get_start_date() val = d.get_year() - years d.set_year(val) - if not not_too_old (d, current_year): + if not not_too_old (d, current_date.get_year()): return True child_death_ref = child.get_death_ref() @@ -683,7 +692,7 @@ def probably_alive(person, db, current_year=None, limit=0): child_death = db.get_event_from_handle(child_death_ref.ref) dobj = child_death.get_date_object() if dobj.get_start_date() != gen.lib.Date.EMPTY: - if not not_too_old (dobj, current_year): + if not not_too_old (dobj, current_date.get_year()): return True if descendants_too_old (child, years + _MIN_GENERATION_YEARS): @@ -758,13 +767,11 @@ def probably_alive(person, db, current_year=None, limit=0): # If there are ancestors that would be too old in the current year # then assume our person must be dead too. - if ancestors_too_old (person, current_year): - #print person.get_primary_name().get_name(), " is dead because ancestors are too old." + if ancestors_too_old (person, current_date.get_year()): return False # If we can't find any reason to believe that they are dead we # must assume they are alive. - #print person.get_primary_name().get_name(), " is probably alive." return True def not_too_old(date, current_year=None): diff --git a/src/gen/lib/date.py b/src/gen/lib/date.py index 29c323ced..bc0ca564c 100644 --- a/src/gen/lib/date.py +++ b/src/gen/lib/date.py @@ -537,6 +537,25 @@ class Date: self.dateval = tuple(dv) self._calc_sort_value() + def set_yr_mon_day_offset(self, year=0, month=0, day=0): + """ + Sets the year, month, and day values by offset + """ + dv = list(self.dateval) + dv[Date._POS_YR] += year + dv[Date._POS_MON] += month + dv[Date._POS_DAY] += day + self.dateval = tuple(dv) + self._calc_sort_value() + + def copy_offset_ymd(self, year=0, month=0, day=0): + """ + Returns a Date copy based on year, month, and day offset + """ + retval = Date(self) + retval.set_yr_mon_day_offset(year, month, day) + return retval + def set_year(self, year): """ Sets the year value @@ -760,7 +779,6 @@ class Date: """ return Date._calendar_change[Date.CAL_GREGORIAN](self.sortval + value) - # if __name__ == "__main__": # # Test function. Call it as follows from the command line (so as to find # # imported modules): diff --git a/src/gen/proxy/living.py b/src/gen/proxy/living.py index 2ccb3a902..d382c67b8 100644 --- a/src/gen/proxy/living.py +++ b/src/gen/proxy/living.py @@ -69,7 +69,8 @@ class LivingProxyDb(ProxyDbBase): """ ProxyDbBase.__init__(self, db) self.mode = mode - self.current_year = current_year + self.current_date = gen.lib.Date() + self.current_date.set_year(current_year) self.years_after_death = years_after_death def get_person_from_handle(self, handle): @@ -366,7 +367,7 @@ class LivingProxyDb(ProxyDbBase): def __is_living(self,person): return probably_alive( person, self.db, - self.current_year, + self.current_date, self.years_after_death ) def __remove_living_from_family(self,family): diff --git a/src/plugins/Calendar.py b/src/plugins/Calendar.py index 971b907d6..85407088b 100644 --- a/src/plugins/Calendar.py +++ b/src/plugins/Calendar.py @@ -102,6 +102,14 @@ def dst(year, area="us"): stop = "%d/%d/%d" % (year, 10,(31 - (math.floor(year * 5 / 4) + 1) % 7)) # Oct return (start, stop) +def make_date(year, month, day): + """ + Returns a Date object of the particular year/month/day. + """ + retval = gen.lib.Date() + retval.set_yr_mon_day(year, month, day) + return retval + #------------------------------------------------------------------------ # # Calendar @@ -309,8 +317,7 @@ class Calendar(Report): if birth_ref: birth_event = self.database.get_event_from_handle(birth_ref.ref) birth_date = birth_event.get_date_object() - alive = probably_alive(person, self.database, self.year) - if self.birthdays and birth_date != None and ((self.alive and alive) or not self.alive): + if self.birthdays and birth_date != None: year = birth_date.get_year() month = birth_date.get_month() day = birth_date.get_day() @@ -335,8 +342,10 @@ class Calendar(Report): father_lastname = father.get_primary_name().get_surname() short_name = self.get_name(person, father_lastname) if age >= 0: - self.add_day_item("%s, %d" % (short_name, age), year, month, day) - if self.anniversaries and ((self.alive and alive) or not self.alive): + alive = probably_alive(person, self.database, make_date(self.year, month, day)) + if ((self.alive and alive) or not self.alive): + self.add_day_item("%s, %d" % (short_name, age), self.year, month, day) + if self.anniversaries: family_list = person.get_family_handle_list() for fhandle in family_list: fam = self.database.get_family_from_handle(fhandle) @@ -352,9 +361,6 @@ class Calendar(Report): if spouse: spouse_name = self.get_name(spouse) short_name = self.get_name(person) - if self.alive: - if not probably_alive(spouse, self.database, self.year): - continue # TEMP: this will hanlde ordered events # GRAMPS 3.0 will have a new mechanism for start/stop events are_married = None @@ -381,8 +387,11 @@ class Calendar(Report): 'person' : short_name, 'nyears' : years, } - self.add_day_item(text, year, month, day) - + alive1 = probably_alive(person,self.database,make_date(self.year,month,day)) + alive2 = probably_alive(spouse,self.database,make_date(self.year,month,day)) + if ((self.alive and alive1 and alive2) or not self.alive): + self.add_day_item(text, self.year, month, day) + class CalendarReport(Calendar): """ The Calendar text report """ def write_report(self):