How do I get an age in years and date on pandas - python

Here's my data
Customer_id Date-of-birth
1 1992-07-02
2 1991-07-03
Here's my code
import datetime as dt
df['now'] = dt.datetime.now()
df['age'] = df['now'].dt.date - df['Date-of-birth']
Here's the result
Customer_id Date-of-birth age
1 1992-07-02 xxxx days
2 1991-07-03 xxxx days
The result that I want is
Customer_id Date-of-birth age
1 1992-07-02 26 years 22 days
2 1991-07-03 27 years 21 days
Just let you now, by df.dtypes, Date-of-birth is an object because is based on customer input in dropdown
How can I achieve this? I hope the question is clear enough

Use this solution with custom function, because count it is not easy because leaps years:
from dateutil.relativedelta import relativedelta
def f(end):
r = relativedelta(pd.to_datetime('now'), end)
return '{} years {} days'.format(r.years, r.days)
df['age'] = df["Date-of-birth"].apply(f)
print (df)
Customer_id Date-of-birth age
0 1 1992-07-02 26 years 22 days
1 2 1991-07-03 27 years 21 days

Input:
import pandas as pd
import datetime as dt
now = dt.datetime.now()
for i in range(0, len(df)):
diff = now - dt.datetime.strptime(df['Date-of-Birth'][i], '%Y-%m-%d')
years = diff.days // 365
days = diff.days - (years*365)
df['age'][i] = str(years) + ' years ' + str(days) + ' days'
print(df)
Output:
Customer_id Date-of-Birth age
1 1992-07-04 26 years 25 days
2 1991-07-04 27 years 26 days

Maybe you could use something like the following. Note that it relies on the fact that the average year has 365.25 days, so it may be a day off sometimes.
import datetime as dt
def year_days_diff(x):
diff = (dt.datetime.now() - x).days
return str(int(diff / 365.25)) + ' years ' + str(int(diff / 365.25 % 1 * 365.25)) + ' days'
Example:
birth_date = dt.datetime.now() - dt.timedelta(10000)
year_days_diff(birth_date)
output:
'27 years 138 days'

This could give you age by rounding to years.
ref_date = dt.datetime.now()
df['age'] = df['Date-of-birth'].apply(lambda x: len(pd.date_range(start = x, end = ref_date, freq = 'Y')))

Use astype('<m8[Y]')
Ex:
df['age'] = (pd.to_datetime('now') - df['Date-of-birth']).astype('<m8[Y]')
Demo:
import pandas as pd
df = pd.DataFrame({"Date-of-birth": pd.to_datetime(['1992-07-24', '1991-07-24'])})
df["age"] = (pd.to_datetime('now') - df["Date-of-birth"]).astype('<m8[Y]')
print(df)
Output:
Date-of-birth age
0 1992-07-24 25.0
1 1991-07-24 27.0

Related

How to calculate age as years, months, and days?

I have two pairs of date data:
date_pair1 = [datetime.datetime(2021,3,1) , datetime.datetime(2020,2,1)]
date_pair2 = [datetime.datetime(2021,4,1) , datetime.datetime(2021,3,1)]
With Python:
delta1 = (date_pair1[0]-date_pair1[1]).days
delta2 = (date_pair2[0]-date_pair2[1]).days
year = 365
month = 30
age1 = f"{delta1//365} year {(delta1%365)//30} month {(delta1%365)%30} day"
age2 = f"{delta2//365} year {(delta2%365)//30} month {(delta2%365)%30} day"
print(age1,"-",age2)
Result:
1 year 0 month 29 day - 0 year 1 month 1 day
With Excel:
E5 cell:1.02.2020 F5 cell:1.03.2021
E6 cell:1.03.2021 F6 cell:1.04.2021
Using DATEDIF function:
=CONCAT(DATEDIF(E5,F5,"Y")," year ",DATEDIF(E5,F5,"YM")," month ",DATEDIF(E5,F5,"MD")," day")
=CONCAT(DATEDIF(E6,F6,"Y")," year ",DATEDIF(E6,F6,"YM")," month ",DATEDIF(E6,F6,"MD")," day")
1 year 1 month 0 day - 0 year 1 month 0 day
How can I get the results in Excel using python?
Use relativedelta
date_pair1 = [datetime.datetime(2021,3,1) , datetime.datetime(2020,2,1)]
date_pair2 = [datetime.datetime(2021,4,1) , datetime.datetime(2021,3,1)]
from dateutil.relativedelta import relativedelta
delta1 = relativedelta(date_pair1[0],date_pair1[1])
delta2 = relativedelta(date_pair2[0],date_pair2[1])
age1 = f"{delta1.years} year {delta1.months} month {delta1.days} day"
age2 = f"{delta2.years} year {delta2.months} month {delta2.days} day"
print(age1,"-",age2)

Generate list of months between interval in python and print

I want to generate a python list containing all months occurring between two dates, which is separated by year in array as follow:
startdate = "2014-10-10" # input start date
enddate = "2016-01-07" # input end date
month_list = [['Oct-14', 'Nov-14', 'Dec-14'], ['Jan-15', 'Feb-15', 'Mar-15', 'Apr-15', 'May-15', 'Jun-15', 'Jul-15', 'Aug-15', 'Sep-15', 'Oct-15', 'Nov-15', 'Dec-15'], ['Jan-16']] # output
i tried this but it display only two year interval in array
import calendar
from datetime import *
startdate = datetime.strptime("2015-09-10", "%Y-%m-%d")
enddate = datetime.strptime("2016-5-15", "%Y-%m-%d")
month_str = calendar.month_name
curryear = startdate.year
months = []
yearss=[]
temp=[]
while startdate < enddate:
month = startdate.month
year = startdate.year
day = startdate.day
mon_str = month_str[month][0:3]
next_month = month + 1 if month != 12 else 1
if curryear == year:
months.append("{0}-{1}".format(mon_str, str(year)[-2:]))
startdate = startdate.replace(month=next_month, year=year)
next_year = year+1 if next_month==1 else year
if curryear != next_year:
startdate = startdate.replace(month=next_month, year=next_year)
temp.append("{0}-{1}".format(mon_str, str(next_year)[-2:]))
months.append(temp)
print(months)
Output:
['Sep-15', 'Oct-15', 'Nov-15', 'Dec-15', ['Dec-16', 'Jan-16', 'Feb-16', 'Mar-16', 'Apr-16', 'May-16']]
Solution without pandas.
(you can also use it without dateutils)
(but then you've to manually count the months)
import datetime
from dateutil.relativedelta import relativedelta
startdate = datetime.datetime.strptime("2014-10-10", "%Y-%m-%d")
enddate = datetime.datetime.strptime("2016-01-07", "%Y-%m-%d")
# truncate the dates
startdate = startdate.replace(day=1)
enddate = enddate.replace(day=1)
# keep track of the series
dates = []
# create series by year
dates_years = []
current_year = startdate.year
while startdate <= enddate:
# if the current year is not equal to the value of startdate.year
if startdate.year != current_year:
# update current year
current_year = startdate.year
# add the dates_year to dates
dates.append(dates_years)
# empty dates_years
dates_years = []
# store the date in current year
dates_years.append(startdate.strftime("%b-%y"))
# add a month
startdate += relativedelta(months=1)
else:
# add the last part
if len(dates_years) > 0:
dates.append(dates_years)
result: dates
[['Oct-14', 'Nov-14', 'Dec-14'],
['Jan-15',
'Feb-15',
'Mar-15',
'Apr-15',
'May-15',
'Jun-15',
'Jul-15',
'Aug-15',
'Sep-15',
'Oct-15',
'Nov-15',
'Dec-15'],
['Jan-16']]
You can do this via pandas:
import numpy as np
import pandas as pd
import datetime
from dateutil.relativedelta import relativedelta
startdate = "2014-10-10" # input start date
enddate = "2016-01-07"
## optionally - end date should be 1 + month, but date_range does also accept string-values
# cast the dates
startdate = datetime.date.fromisoformat(startdate)
enddate = datetime.date.fromisoformat(enddate) + relativedelta(months=1) # add 1 month
# convert to a data frame
dtr = pd.date_range(start=startdate, end=enddate, freq="M")
result
DatetimeIndex(['2014-10-31', '2014-11-30', '2014-12-31', '2015-01-31',
'2015-02-28', '2015-03-31', '2015-04-30', '2015-05-31',
'2015-06-30', '2015-07-31', '2015-08-31', '2015-09-30',
'2015-10-31', '2015-11-30', '2015-12-31', '2016-01-31'],
dtype='datetime64[ns]', freq='M')
step 2:
df = pd.DataFrame(dtr, columns=["dates"])
df['year'] = df.dates.dt.year
# add the result
df['output'] = [x.strftime("%b-%y") for x in df.dates]
result
dates year output
0 2014-10-31 2014 Oct-14
1 2014-11-30 2014 Nov-14
2 2014-12-31 2014 Dec-14
3 2015-01-31 2015 Jan-15
4 2015-02-28 2015 Feb-15
5 2015-03-31 2015 Mar-15
6 2015-04-30 2015 Apr-15
7 2015-05-31 2015 May-15
8 2015-06-30 2015 Jun-15
9 2015-07-31 2015 Jul-15
10 2015-08-31 2015 Aug-15
11 2015-09-30 2015 Sep-15
12 2015-10-31 2015 Oct-15
13 2015-11-30 2015 Nov-15
14 2015-12-31 2015 Dec-15
15 2016-01-31 2016 Jan-16
step 3
group by year, and add dates into a list:
[list(output) for year, output in df.groupby('year').output]
result
[['Oct-14', 'Nov-14', 'Dec-14'],
['Jan-15',
'Feb-15',
'Mar-15',
'Apr-15',
'May-15',
'Jun-15',
'Jul-15',
'Aug-15',
'Sep-15',
'Oct-15',
'Nov-15',
'Dec-15'],
['Jan-16']]

last month to last 10 month pandas datetime

How to create two variables.
1 - variable last month
2 - variable past 10 month
Like the date that represents TODAY - 10 months, so for example:2020/02/05 - 10 months = 2019/04/05.
my code:
import datime
# 1- last month
month = datetime.datetime.now().month
year = datetime.datetime.now().year
last_month = f"{year}/{month-1}/01"
>>>
"2020/01/05"
# Past 12 months
past_10month = datetime.datetime.today()
past_10month = f"{past_10month -285}"
>>>
# DO NOT WORK
# EXPECTED RESULT:
# "2019/04/05"
from datetime import datetime
from dateutil.relativedelta import relativedelta
dt = datetime.now()
last_month = (dt - relativedelta(months=1)).date()
last_year = (dt - relativedelta(months=10)).date()
Output:
2020-01-05
2019-04-05

How do I create a days_in_year function using Pandas?

I'm trying to create a simply column using Pandas that will calculate the number of days in the year of the adjacent date column.
I've already done this fairly easily for the numbers of days in the month using the daysinmonth attribute of DatetimeIndex, with the following:
def daysinmonth(row):
x = pd.DatetimeIndex(row['Date']).daysinmonth
return x
daysinmonth(df)
I'm having trouble to mimic these results for year without the nifty pre-defined attribute.
my dataframe looks like the following (sans the days_in_year column since i'm trying to create that):
Date Days_in_month Days_in_year
1 2/28/2018 28 365
2 4/14/2019 30 365
3 1/1/2020 31 366
4 2/15/2020 29 366
Thanks to anyone who takes a look!
Get the mode of year by 4 , equal to 0 means 366, else means 365(Notice this will not include the special cases , You can check the update function and the link I provided)
(pd.to_datetime(df.Date,format='%m/%d/%Y').dt.year%4).eq(0).map({True:366,False:365})
Out[642]:
1 365
2 365
3 366
4 366
Name: Date, dtype: int64
You can using this which is more accurate for decided leap year ,definition from this site
def daysinyear(x):
if x%4==0 :
if x%100==0:
if x%400==0:
return(366)
else:
return (365)
else :
return(365)
else:
return(365)
(pd.to_datetime(df.Date,format='%m/%d/%Y').dt.year%4).apply(daysinyear)
Out[656]:
1 365
2 365
3 366
4 366
Name: Date, dtype: int64
You can also use YearEnd. You'll get a timedelta64 column with this method.
import pandas as pd
from pandas.tseries.offsets import YearEnd
df['Date'] = pd.to_datetime(df.Date)
(df.Date + YearEnd(1)) - (df.Date - YearEnd(1))
1 365 days
2 365 days
3 366 days
4 366 days
Name: Date, dtype: timedelta64[ns]
Here's another way using periods:
df['Date'].dt.to_period('A').dt.to_timestamp('A').dt.dayofyear
Output:
1 365
2 365
3 366
4 366
Name: Date, dtype: int64
I would do something like this>
import datetime
import numpy as np
def func(date):
year = date.year
begin = datetime.datetime(year,1,1)
end = datetime.datetime(year,12,31)
diff = (end - begin)
result = np.timedelta64(diff, "D").astype("int")
return result
print(func(datetime.datetime(2016,12,31)))
One solution is to take the first day of one year and of the next year. Then calculate the difference. You can then apply this using pd.Series.apply:
def days_in_year(x):
day1 = x.replace(day=1, month=1)
day2 = day1.replace(year=day1.year+1)
return (day2 - day1).days
df['Date'] = pd.to_datetime(df['Date'])
df['Days_in_year'] = df['Date'].apply(days_in_year)
print(df)
Date Days_in_month Days_in_year
1 2018-02-28 28 365
2 2019-04-14 30 365
3 2020-01-01 31 366
4 2020-02-15 29 366
You can use the basic formula to check if a year is a leap year and add the result to 365 to get the number of days in a year.
# Not needed if df ['Date'] is already of type datetime
dates = pd.to_datetime(df['Date'])
years = dates.dt.year
ndays = 365 + ((years % 4 == 0) & ((years % 100 != 0) | (years % 400 == 0))).astype(int)

Age from birthdate in python

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.
That can be done much simpler considering that int(True) is 1 and int(False) is 0, and tuples comparison goes from left to right:
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
Update: Use Danny's solution, it's better
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)
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)`
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
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
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.
If you're looking to print this in a page using django templates, then the following might be enough:
{{ birth_date|timesince }}
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
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)
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
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.
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 :)
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
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
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
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.timetuple()[1:3] < born.timetuple()[1:3])
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_with_seconds(born):
today = datetime.now()
return today.year - born.year - (today.timetuple()[1:6] < born.timetuple()[1:6])
This will work for born both being a date or a datetime object.
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
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}')

Categories

Resources