thebjorn wrote: > For the purpose of finding someone's age I was looking for a way to > find how the difference in years between two dates, so I could do > something like: > > age = (date.today() - born).year > > but that didn't work (the timedelta class doesn't have a year > accessor). > > I looked in the docs and the cookbook, but I couldn't find anything, so > I came up with: > > def age(born): > now = date.today() > birthday = date(now.year, born.month, born.day)
Bad luck if the punter was born on 29 Feb and the current year is not a leap year. > return now.year - born.year - (birthday > now and 1 or 0) Holy code bloat, Batman! Try this: return now.year - born.year - (birthday > now) > > i.e. calculate the "raw" years first and subtract one if he hasn't had > his birthday yet this year... It works, but I'd rather use a standard > and generic approach if it exists...? > It's the irregular-size months that cause the problems. If you can work out the months difference, then just floor_div by 12 to get the years difference. Below is some code from the ancient times when everybody and his dog each had their own date class :-) HTH, John 8<--- methods from a date class def months_until(self, to_date): """Return number of months between from_date (self) and to_date. """ from_date = self signum = 1 if from_date > to_date: from_date, to_date = to_date, from_date signum = -1 d1, m1, y1 = from_date.day, from_date.month, from_date.year d2, m2, y2 = to_date.day, to_date.month, to_date.year mdiff = (y2 - y1) * 12 + m2 - m1 if d2 < d1 and (d2 < 28 or d2 != last_day_of_month(y2, m2)): # the test d2 < 28 is not necessary; it is an optimisation # to avoid calling last_day_of_month unnecessarily mdiff = mdiff - 1 return mdiff * signum def years_until(self, to_date): """Return number of years between from_date (self) and to_date. """ md = self.months_until(to_date) if md >= 0: return md // 12 else: # ensure division truncates towards zero return -((-md) // 12) 8<--- module-level functions and constants # days in month _dim = (None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) def last_day_of_month(y, m): """Return day (1..31) which is last day of month m in year y """ if m == 2: return 28 + _leap(y) else: if not (1 <= m <= 12): raise DateError, "month not in 1..12" return _dim[m] def _leap(y): if y % 4: return 0 if y % 100: return 1 if y % 400: return 0 return 1 8<---- -- http://mail.python.org/mailman/listinfo/python-list