年龄从python出生date

如何从今天的date和人的出生datefindpython的年龄? 生日是来自Django模型中的DateField。

考虑到int(True)是1,int(False)是0,可以简单得多:

 from datetime import date def calculate_age(born): today = date.today() return today.year - born.year - ((today.month, today.day) < (born.month, born.day)) 
 from datetime import date def calculate_age(born): today = date.today() try: birthday = born.replace(year=today.year) except ValueError: # raised when birth date is February 29 and the current year is not a leap year birthday = born.replace(year=today.year, month=born.month+1, day=1) if birthday > today: return today.year - born.year - 1 else: return today.year - born.year 

更新:使用丹尼的解决scheme ,它更好

 from datetime import date days_in_year = 365.2425 age = int((date.today() - birth_date).days / days_in_year) 

在Python 3中,您可以在datetime.timedelta上执行除法:

 from datetime import date, timedelta age = (date.today() - birth_date) // timedelta(days=365.2425) 

最简单的方法是使用python-dateutil

 import datetime import dateutil def birthday(date): # Get the current date now = datetime.datetime.utcnow() now = now.date() # Get the difference between the current date and the birthday age = dateutil.relativedelta.relativedelta(now, date) age = age.years return age 
 from datetime import date def age(birth_date): today = date.today() y = today.year - birth_date.year if today.month < birth_date.month or today.month == birth_date.month and today.day < birth_date.day: y -= 1 return y 

不幸的是,你不能只使用timedelata,因为它使用的最大单位是一天,闰年会使你的计算失效。 因此,如果去年不满,我们可以找出年数然后调整一年:

 from datetime import date birth_date = date(1980, 5, 26) years = date.today().year - birth_date.year if (datetime.now() - birth_date.replace(year=datetime.now().year)).days >= 0: age = years else: age = years - 1 

UPD:

这个解决scheme在29年2月29日发挥作用时确实引起了一个例外。 这是正确的检查:

 from datetime import date birth_date = date(1980, 5, 26) today = date.today() years = today.year - birth_date.year if all((x >= y) for x,y in zip(today.timetuple(), birth_date.timetuple()): age = years else: age = years - 1 

UPD2:

调用多个调用到now()的性能打击是荒谬的,除了极其特殊的情况,并不重要。 使用variables的真正原因是数据不一致的风险。

这种情况下的经典问题是如何处理二月二十九日出生的人。 例如:你需要年满18岁才能投票,开车,买酒等等。如果你是在2004年2月29日出生的,你可以做的第一天是什么日子?2022-02 -28或2022-03-01? AFAICT,大多数是第一个,但less数可能会说后者。

以下代码适合当天出生人口的0.068%(约):

 def age_in_years(from_date, to_date, leap_day_anniversary_Feb28=True): age = to_date.year - from_date.year try: anniversary = from_date.replace(year=to_date.year) except ValueError: assert from_date.day == 29 and from_date.month == 2 if leap_day_anniversary_Feb28: anniversary = datetime.date(to_date.year, 2, 28) else: anniversary = datetime.date(to_date.year, 3, 1) if to_date < anniversary: age -= 1 return age if __name__ == "__main__": import datetime tests = """ 2004 2 28 2010 2 27 5 1 2004 2 28 2010 2 28 6 1 2004 2 28 2010 3 1 6 1 2004 2 29 2010 2 27 5 1 2004 2 29 2010 2 28 6 1 2004 2 29 2010 3 1 6 1 2004 2 29 2012 2 27 7 1 2004 2 29 2012 2 28 7 1 2004 2 29 2012 2 29 8 1 2004 2 29 2012 3 1 8 1 2004 2 28 2010 2 27 5 0 2004 2 28 2010 2 28 6 0 2004 2 28 2010 3 1 6 0 2004 2 29 2010 2 27 5 0 2004 2 29 2010 2 28 5 0 2004 2 29 2010 3 1 6 0 2004 2 29 2012 2 27 7 0 2004 2 29 2012 2 28 7 0 2004 2 29 2012 2 29 8 0 2004 2 29 2012 3 1 8 0 """ for line in tests.splitlines(): nums = [int(x) for x in line.split()] if not nums: print continue datea = datetime.date(*nums[0:3]) dateb = datetime.date(*nums[3:6]) expected, anniv = nums[6:8] age = age_in_years(datea, dateb, anniv) print datea, dateb, anniv, age, expected, age == expected 

这是输出:

 2004-02-28 2010-02-27 1 5 5 True 2004-02-28 2010-02-28 1 6 6 True 2004-02-28 2010-03-01 1 6 6 True 2004-02-29 2010-02-27 1 5 5 True 2004-02-29 2010-02-28 1 6 6 True 2004-02-29 2010-03-01 1 6 6 True 2004-02-29 2012-02-27 1 7 7 True 2004-02-29 2012-02-28 1 7 7 True 2004-02-29 2012-02-29 1 8 8 True 2004-02-29 2012-03-01 1 8 8 True 2004-02-28 2010-02-27 0 5 5 True 2004-02-28 2010-02-28 0 6 6 True 2004-02-28 2010-03-01 0 6 6 True 2004-02-29 2010-02-27 0 5 5 True 2004-02-29 2010-02-28 0 5 5 True 2004-02-29 2010-03-01 0 6 6 True 2004-02-29 2012-02-27 0 7 7 True 2004-02-29 2012-02-28 0 7 7 True 2004-02-29 2012-02-29 0 8 8 True 2004-02-29 2012-03-01 0 8 8 True 

正如@ [Tomasz Zielinski]和@Williams所build议的python-dateutil只能做5行。

 from dateutil.relativedelta import * from datetime import date today = date.today() dob = date(1982, 7, 5) age = relativedelta(today, dob) >>relativedelta(years=+33, months=+11, days=+16)` 

这是一个解决scheme,find一个人的年龄,无论是几年或几个月或几天。

假设一个人的出生date是2012-01-17T00:00:00因此,他的年龄在2013-01-16T00:00:00将是11个月

或者如果他出生于2012-12-17T00:00:00 ,他的年龄在2013-01-12T00:00:00将是26天

或者如果他出生于2000-02-29T00:00:00 ,他的年龄在2012-02-29T00:00:00将是12年

您将需要导入date时间

这里是代码:

 def get_person_age(date_birth, date_today): """ At top level there are three possibilities : Age can be in days or months or years. For age to be in years there are two cases: Year difference is one or Year difference is more than 1 For age to be in months there are two cases: Year difference is 0 or 1 For age to be in days there are 4 possibilities: Year difference is 1(20-dec-2012 - 2-jan-2013), Year difference is 0, Months difference is 0 or 1 """ years_diff = date_today.year - date_birth.year months_diff = date_today.month - date_birth.month days_diff = date_today.day - date_birth.day age_in_days = (date_today - date_birth).days age = years_diff age_string = str(age) + " years" # age can be in months or days. if years_diff == 0: if months_diff == 0: age = age_in_days age_string = str(age) + " days" elif months_diff == 1: if days_diff < 0: age = age_in_days age_string = str(age) + " days" else: age = months_diff age_string = str(age) + " months" else: if days_diff < 0: age = months_diff - 1 else: age = months_diff age_string = str(age) + " months" # age can be in years, months or days. elif years_diff == 1: if months_diff < 0: age = months_diff + 12 age_string = str(age) + " months" if age == 1: if days_diff < 0: age = age_in_days age_string = str(age) + " days" elif days_diff < 0: age = age-1 age_string = str(age) + " months" elif months_diff == 0: if days_diff < 0: age = 11 age_string = str(age) + " months" else: age = 1 age_string = str(age) + " years" else: age = 1 age_string = str(age) + " years" # The age is guaranteed to be in years. else: if months_diff < 0: age = years_diff - 1 elif months_diff == 0: if days_diff < 0: age = years_diff - 1 else: age = years_diff else: age = years_diff age_string = str(age) + " years" if age == 1: age_string = age_string.replace("years", "year").replace("months", "month").replace("days", "day") return age_string 

上述代码中使用的一些额外function是:

 def get_todays_date(): """ This function returns todays date in proper date object format """ return datetime.now() 

 def get_date_format(str_date): """ This function converts string into date type object """ str_date = str_date.split("T")[0] return datetime.strptime(str_date, "%Y-%m-%d") 

现在,我们必须使用像2000-02-29T00:00:00这样的string来提供get_date_format()

它会将其转换为date型对象,该对象将被馈送到get_person_age(date_birth,date_today)

函数get_person_age(date_birth,date_today)将以string格式返回年龄。

如果你打算使用django模板在页面中打印这个,那么下面的代码就足够了:

 {{ birth_date|timesince }} 

扩大丹尼的解决scheme ,但以各种方式报告年轻人的年龄(注意,今天是datetime.date(2015,7,17) ):

 def calculate_age(born): ''' Converts a date of birth (dob) datetime object to years, always rounding down. When the age is 80 years or more, just report that the age is 80 years or more. When the age is less than 12 years, rounds down to the nearest half year. When the age is less than 2 years, reports age in months, rounded down. When the age is less than 6 months, reports the age in weeks, rounded down. When the age is less than 2 weeks, reports the age in days. ''' today = datetime.date.today() age_in_years = today.year - born.year - ((today.month, today.day) < (born.month, born.day)) months = (today.month - born.month - (today.day < born.day)) %12 age = today - born age_in_days = age.days if age_in_years >= 80: return 80, 'years or older' if age_in_years >= 12: return age_in_years, 'years' elif age_in_years >= 2: half = 'and a half ' if months > 6 else '' return age_in_years, '%syears'%half elif months >= 6: return months, 'months' elif age_in_days >= 14: return age_in_days/7, 'weeks' else: return age_in_days, 'days' 

示例代码:

 print '%d %s' %calculate_age(datetime.date(1933,6,12)) # >=80 years print '%d %s' %calculate_age(datetime.date(1963,6,12)) # >=12 years print '%d %s' %calculate_age(datetime.date(2010,6,19)) # >=2 years print '%d %s' %calculate_age(datetime.date(2010,11,19)) # >=2 years with half print '%d %s' %calculate_age(datetime.date(2014,11,19)) # >=6 months print '%d %s' %calculate_age(datetime.date(2015,6,4)) # >=2 weeks print '%d %s' %calculate_age(datetime.date(2015,7,11)) # days old 80 years or older 52 years 5 years 4 and a half years 7 months 6 weeks 7 days 

由于我没有看到正确的实施,我以这种方式logging了我的…

  def age_in_years(from_date, to_date=datetime.date.today()): if (DEBUG): logger.debug("def age_in_years(from_date='%s', to_date='%s')" % (from_date, to_date)) if (from_date>to_date): # swap when the lower bound is not the lower bound logger.debug('Swapping dates ...') tmp = from_date from_date = to_date to_date = tmp age_delta = to_date.year - from_date.year month_delta = to_date.month - from_date.month day_delta = to_date.day - from_date.day if (DEBUG): logger.debug("Delta's are : %i / %i / %i " % (age_delta, month_delta, day_delta)) if (month_delta>0 or (month_delta==0 and day_delta>=0)): return age_delta return (age_delta-1) 

2月28日出生于29日的“18”假设是错误的。 交换界限可以省略…这只是我的代码个人的便利:)

导入date时间

 def age(date_of_birth): if date_of_birth > datetime.date.today().replace(year = date_of_birth.year): return datetime.date.today().year - date_of_birth.year - 1 else: return datetime.date.today().year - date_of_birth.year 

在你的情况下:

 import datetime # your model def age(self): if self.birthdate > datetime.date.today().replace(year = self.birthdate.year): return datetime.date.today().year - self.birthdate.year - 1 else: return datetime.date.today().year - self.birthdate.year 

稍微修改丹尼的解决scheme ,以便于阅读和理解

  from datetime import date def calculate_age(birth_date): today = date.today() age = today.year - birth_date.year full_year_passed = (today.month, today.day) < (birth_date.month, birth_date.day) if not full_year_passed: age -= 1 return age