How can I find an age in python from today’s date and a persons birthdate? The birthdate is a from a DateField in a Django model.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
That can be done much simpler considering that int(True) is 1 and int(False) is 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))
Method 2
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
Update: Use Danny’s solution, it’s better
Method 3
from datetime import date days_in_year = 365.2425 age = int((date.today() - birth_date).days / days_in_year)
In Python 3, you could perform division on datetime.timedelta:
from datetime import date, timedelta age = (date.today() - birth_date) // timedelta(days=365.2425)
Method 4
As suggested by @[Tomasz Zielinski] and @Williams python-dateutil can do it just 5 lines.
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)`
Method 5
The simplest way is using 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
Method 6
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
Method 7
Unfortunately, you cannot just use timedelata as the largest unit it uses is day and leap years will render you calculations invalid. Therefore, let’s find number of years then adjust by one if the last year isn’t full:
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:
This solution really causes an exception when Feb, 29 comes into play. Here’s correct check:
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:
Calling multiple calls to now() a performance hit is ridiculous, it does not matter in all but extremely special cases. The real reason to use a variable is the risk of data incosistency.
Method 8
If you’re looking to print this in a page using django templates, then the following might be enough:
{{ birth_date|timesince }}
Method 9
The classic gotcha in this scenario is what to do with people born on the 29th day of February. Example: you need to be aged 18 to vote, drive a car, buy alcohol, etc … if you are born on 2004-02-29, what is the first day that you are permitted to do such things: 2022-02-28, or 2022-03-01? AFAICT, mostly the first, but a few killjoys might say the latter.
Here’s code that caters for the 0.068% (approx) of the population born on that day:
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
Here’s the output:
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
Method 10
Expanding on Danny’s Solution, but with all sorts of ways to report ages for younger folk (note, today is 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'
Sample code:
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
Method 11
import datetime
Todays date
td=datetime.datetime.now().date()
Your birthdate
bd=datetime.date(1989,3,15)
Your age
age_years=int((td-bd).days /365.25)
Method 12
Here is a solution to find age of a person as either years or months or days.
Lets say a person’s date of birth is 2012-01-17T00:00:00
Therefore, his age on 2013-01-16T00:00:00 will be 11 months
or if he is born on 2012-12-17T00:00:00,
his age on 2013-01-12T00:00:00 will be 26 days
or if he is born on 2000-02-29T00:00:00,
his age on 2012-02-29T00:00:00 will be 12 years
You will need to import datetime.
Here is the code:
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
Some extra functions used in the above codes are:
def get_todays_date():
"""
This function returns todays date in proper date object format
"""
return datetime.now()
And
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")
Now, we have to feed get_date_format() with the strings like 2000-02-29T00:00:00
It will convert it into the date type object which is to be fed to get_person_age(date_birth, date_today).
The function get_person_age(date_birth, date_today) will return age in string format.
Method 13
As I did not see the correct implementation, I recoded mine this way…
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)
Assumption of being “18” on the 28th of Feb when born on the 29th is just wrong.
Swapping the bounds can be left out … it is just a personal convenience for my code 🙂
Method 14
Extend to Danny W. Adair Answer, to get month also
def calculate_age(b):
t = date.today()
c = ((t.month, t.day) < (b.month, b.day))
c2 = (t.day< b.day)
return t.year - b.year - c,c*12+t.month-b.month-c2
Method 15
A slightly more elegant solution than @DannyWAdairs solution might be to work with the .timetuple() method [Python-doc]:
from datetime import date
def calculate_age(born):
today = date.today()
return today.year - born.year - (today<strong>.timetuple()[1:3]</strong> < born<strong>.timetuple()[1:3]</strong>)
You can easily use this to generalize this further to increase its granularity to seconds, such that the age increments if it is greater than or equal to the number of seconds of that day, if born is for example a datetime object:
from datetime import datetime
def calculate_age<b>_with_seconds</b>(born):
today = datetime.now()
return today.year - born.year - (today<strong>.timetuple()[1:6]</strong> < born<strong>.timetuple()[1:6]</strong>)
This will work for born both being a date or a datetime object.
Method 16
import datetime
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
In your case:
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
Method 17
Slightly modified Danny’s solution for easier reading and understanding
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
Method 18
serializers.py
age = serializers.SerializerMethodField('get_age')
class Meta:
model = YourModel
fields = [..,'','birthdate','age',..]
import datetime
def get_age(self, instance):
return datetime.datetime.now().year - instance.birthdate.year
Method 19
You can use Python 3 to do all this. Just run the following code and see.
# Creating a variables:
greeting = "Hello, "
name = input("what is your name?")
birth_year = input("Which year you were born?")
response = "Your age is "
# Converting string variable to int:
calculation = 2020 - int(birth_year)
# Printing:
print(f'{greeting}{name}. {response}{calculation}')
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0