Comment puis-je trouver un âge en python à partir de la date d'aujourd'hui et de la date de naissance d'une personne? La date de naissance provient d'un DateField dans un modèle Django.
a nitpick: date.today()renvoie la date dans le fuseau horaire local qui peut être différente du lieu de naissance. Vous devrez peut-être utiliser explicitement les fuseaux horaires
jfs
10
Cela dépend probablement de votre définition de «l'âge». À toutes fins pratiques, un anniversaire est généralement donné sous forme de date et non de date-heure sensible au fuseau horaire (c'est-à-dire que «né» ne contient pas les détails). La plupart des gens ne sont pas nés à minuit précis (donc observez généralement prématurément :-)), et quand dans un fuseau horaire différent, je suppose que la plupart des gens célèbrent leur anniversaire à l'heure locale (c'est ce que je fais, je vis 10-12h à l'avance de mon lieu de naissance). Si "born" était une date-heure sensible au fuseau horaire, vous pourriez utiliser l'arithmétique de pytz et normaliser () - peut-être intéressant pour un logiciel d'astrologie?
Danny W.Adair
2
Je suis entièrement d'accord dans le contexte des âges humains, mais votre formule peut être utilisée dans un contexte plus large. Bien que personnellement je ne fête jamais mon anniversaire même une heure plus tôt en raison d'une tradition familiale et en tant que programmeur, il est trivial de calculer l'heure où que je sois.
jfs
@pyd: born est une date / datetime
kjagiello
68
from datetime import datedef calculate_age(born):
today = date.today()try:
birthday = born.replace(year=today.year)exceptValueError:# 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 -1else:return today.year - born.year
Par principe, votre exceptbloc ne doit intercepter que la seule exception spécifique qui pourrait être déclenchée.
Daenyth
1
@Daenyth: Bon appel ... Je pense que c'est un ValueError. Actualisé.
mpen
Je vais même jusqu'à tester le message de l'exception pour m'assurer que c'est ce que j'attends. Même avec le code ci-dessus, il est possible qu'une ValueError soit levée, mais ce n'est pas la ValueError que vous attendez.
Randy Syring du
+ par exception mais, y a-t-il un problème dans mon ? Je pense que c'est assez simple. def calculate_age(dob)
Grijesh Chauhan
1
@GrijeshChauhan: Oui, le vôtre ne fonctionne pas. datetime.date(2014, 1, 1)donne -1, il devrait donner 0. Vous today > dobvérifiez si la date de naissance est dans le passé, pas plus tôt cette même année. datetime.date.today()inclut des informations sur l'année, c'est pourquoi je la remplace par l'année en cours dans ma solution.
mpen
18
from datetime import date
days_in_year =365.2425
age = int((date.today()- birth_date).days / days_in_year)
Dans Python 3, vous pouvez effectuer une division sur datetime.timedelta:
from datetime import date, timedelta
age =(date.today()- birth_date)// timedelta(days=365.2425)
chaque quatrième année est une année bissextile sauf que chaque centième année n'est pas une année bissextile sauf que chaque quatre centième année est une année bissextile. essayez days_in_year = 365.2425
Dan
3
@Dan: la différence entre l' 365.25année civile julienne ( ) et grégorienne ( 365.2425) est inférieure à un jour si vous vivez moins de 130 ans.
jfs
4
Cela ne fonctionne pas pour certaines dates: (date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425)devrait revenir 13, mais il revient 12. Sans sol, le résultat est 12.999582469181433.
href_
13
Comme suggéré par @ [Tomasz Zielinski] et @Williams python-dateutil peut le faire seulement 5 lignes.
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)`
Le moyen le plus simple est d'utiliser python-dateutil
import datetimeimport dateutildef 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.yearsreturn age
Cela ne fonctionne pas correctement lorsque l'anniversaire est le 29 février et la date d'aujourd'hui est le 28 février (cela fonctionnera comme si aujourd'hui était le 29 février).
Trey Hunner
6
from datetime import datedef age(birth_date):
today = date.today()
y = today.year - birth_date.yearif today.month < birth_date.month or today.month == birth_date.month and today.day < birth_date.day:
y -=1return y
instance de date ou un objet comme celui-ci, docs.python.org/3/library/datetime.html#datetime.date, faute de frappe corrigée.
gzerone
5
Malheureusement, vous ne pouvez pas simplement utiliser les données temporelles car la plus grande unité utilisée est le jour et les années bissextiles rendront vos calculs invalides. Par conséquent, trouvons le nombre d'années puis ajustons de un si la dernière année n'est pas pleine:
from datetime import date
birth_date = date(1980,5,26)
years = date.today().year - birth_date.yearif(datetime.now()- birth_date.replace(year=datetime.now().year)).days >=0:
age = yearselse:
age = years -1
MàJ:
Cette solution provoque vraiment une exception lorsque le 29 février entre en jeu. Voici la vérification correcte:
from datetime import date
birth_date = date(1980,5,26)
today = date.today()
years = today.year - birth_date.yearif all((x >= y)for x,y in zip(today.timetuple(), birth_date.timetuple()):
age = yearselse:
age = years -1
Upd2:
Appeler plusieurs appels à now()un hit de performance est ridicule, cela n'a pas d'importance dans tous les cas, mais extrêmement spéciaux. La vraie raison d'utiliser une variable est le risque d'incosistance des données.
Merci, j'ai découvert cela en faisant quelques tests - et j'ai trouvé un code similaire trouvé à partir du lien d'AndiDog.
tkalve
3
Avertissement 1: vous utilisez datetime.datetime au lieu de datetime.date. Strike 2: Votre code est laid et inefficace. Appel de datetime.now () TROIS fois ?? Grève 3: Date de naissance 29 février 2004 et date d'aujourd'hui 28 février 2010 devrait renvoyer l'âge de 6 ans, pas mourir en criant "ValueError: le jour est hors de portée pour le mois". Tu es dehors!
John Machin
Désolé, votre code "Upd" est encore plus baroque et cassé que la première tentative - rien à voir avec le 29 février; ça échoue dans BEAUCOUP de cas simples comme le 15/06/2009 au 02/07/2010 ... la personne a évidemment un peu plus d'un an mais on retire un an car le test des jours (2> = 15) échoue. Et évidemment, vous ne l'avez pas testé - il contient une erreur de syntaxe.
John Machin
4
Le truc classique dans ce scénario est ce qu'il faut faire avec les personnes nées le 29 février. Exemple: vous devez avoir 18 ans pour voter, conduire une voiture, acheter de l'alcool, etc ... si vous êtes né le 29/02/2004, quel est le premier jour où vous êtes autorisé à faire de telles choses: 2022-02 -28 ou 2022-03-01? AFAICT, principalement le premier, mais quelques ravisseurs pourraient dire ce dernier.
Voici le code qui s'adresse aux 0,068% (environ) de la population née ce jour-là:
N'utilisez pas Django |timesincepour calculer un delta temporel sur plusieurs années car il ne tient pas compte des années bissextiles et donne donc des résultats inexacts. Voir le ticket Django # 19210 pour plus d'informations à ce sujet.
jnns
Je ne savais pas ça. Merci.
Anoyz
2
Voici une solution pour trouver l'âge d'une personne en années, en mois ou en jours.
Disons que la date de naissance d'une personne est le 2012-01-17T00: 00: 00
Par conséquent, son âge au 2013-01-16T00: 00: 00 sera de 11 mois
ou s'il est né le 2012-12-17T00: 00: 00 , son âge le 2013-01-12T00: 00: 00 sera de 26 jours
ou s'il est né le 2000-02-29T00: 00: 00 , son âge le 2012-02-29T00: 00: 00 sera de 12 ans
Vous devrez importer datetime .
Voici le 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 -1else:
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 -1elif months_diff ==0:if days_diff <0:
age = years_diff -1else:
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
Certaines fonctions supplémentaires utilisées dans les codes ci-dessus sont:
def get_todays_date():"""
This function returns todays date in proper date object format
"""return datetime.now()
Et
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")
Maintenant, nous devons alimenter get_date_format () avec les chaînes comme 2000-02-29T00: 00: 00
Il le convertira en objet de type date qui doit être alimenté par get_person_age (date_birth, date_today) .
La fonction get_person_age (date_birth, date_today) retournera age au format chaîne.
Élargissement de la solution de Danny , mais avec toutes sortes de façons de signaler l'âge des jeunes (notez que c'est aujourd'hui 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:return80,'years or older'if age_in_years >=12:return age_in_years,'years'elif age_in_years >=2:
half ='and a half 'if months >6else''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'
Exemple de code:
print'%d %s'%calculate_age(datetime.date(1933,6,12))# >=80 yearsprint'%d %s'%calculate_age(datetime.date(1963,6,12))# >=12 yearsprint'%d %s'%calculate_age(datetime.date(2010,6,19))# >=2 yearsprint'%d %s'%calculate_age(datetime.date(2010,11,19))# >=2 years with halfprint'%d %s'%calculate_age(datetime.date(2014,11,19))# >=6 monthsprint'%d %s'%calculate_age(datetime.date(2015,6,4))# >=2 weeksprint'%d %s'%calculate_age(datetime.date(2015,7,11))# days old80 years or older
52 years
5 years
4and a half years
7 months
6 weeks
7 days
Comme je n'ai pas vu l'implémentation correcte, j'ai recodé le mien de cette façon ...
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>0or(month_delta==0and day_delta>=0)):return age_delta
return(age_delta-1)
L'hypothèse d'être "18" le 28 février à la naissance le 29 est tout simplement erronée. Changer les limites peut être omis ... c'est juste une commodité personnelle pour mon code :)
La solution de Danny légèrement modifiée pour une lecture et une compréhension plus faciles
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)ifnot full_year_passed:
age -=1return age
datetime
module standard ne suffit pas, vous pouvez essayer: labix.org/python-dateutildateutil.relativedelta.relativedelta
Réponses:
Cela peut être fait beaucoup plus simplement en considérant que int (True) est 1 et int (False) est 0:
la source
date.today()
renvoie la date dans le fuseau horaire local qui peut être différente du lieu de naissance. Vous devrez peut-être utiliser explicitement les fuseaux horairesMise à jour: utilisez la solution de Danny , c'est mieux
la source
except
bloc ne doit intercepter que la seule exception spécifique qui pourrait être déclenchée.ValueError
. Actualisé.def calculate_age(dob)
datetime.date(2014, 1, 1)
donne -1, il devrait donner 0. Voustoday > dob
vérifiez si la date de naissance est dans le passé, pas plus tôt cette même année.datetime.date.today()
inclut des informations sur l'année, c'est pourquoi je la remplace par l'année en cours dans ma solution.Dans Python 3, vous pouvez effectuer une division sur
datetime.timedelta
:la source
365.25
année civile julienne ( ) et grégorienne (365.2425
) est inférieure à un jour si vous vivez moins de 130 ans.(date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425)
devrait revenir13
, mais il revient12
. Sans sol, le résultat est12.999582469181433
.Comme suggéré par @ [Tomasz Zielinski] et @Williams python-dateutil peut le faire seulement 5 lignes.
la source
Le moyen le plus simple est d'utiliser
python-dateutil
la source
la source
Malheureusement, vous ne pouvez pas simplement utiliser les données temporelles car la plus grande unité utilisée est le jour et les années bissextiles rendront vos calculs invalides. Par conséquent, trouvons le nombre d'années puis ajustons de un si la dernière année n'est pas pleine:
MàJ:
Cette solution provoque vraiment une exception lorsque le 29 février entre en jeu. Voici la vérification correcte:
Upd2:
Appeler plusieurs appels à
now()
un hit de performance est ridicule, cela n'a pas d'importance dans tous les cas, mais extrêmement spéciaux. La vraie raison d'utiliser une variable est le risque d'incosistance des données.la source
Le truc classique dans ce scénario est ce qu'il faut faire avec les personnes nées le 29 février. Exemple: vous devez avoir 18 ans pour voter, conduire une voiture, acheter de l'alcool, etc ... si vous êtes né le 29/02/2004, quel est le premier jour où vous êtes autorisé à faire de telles choses: 2022-02 -28 ou 2022-03-01? AFAICT, principalement le premier, mais quelques ravisseurs pourraient dire ce dernier.
Voici le code qui s'adresse aux 0,068% (environ) de la population née ce jour-là:
Voici le résultat:
la source
Si vous cherchez à imprimer ceci dans une page à l'aide de modèles django, alors ce qui suit peut suffire:
la source
|timesince
pour calculer un delta temporel sur plusieurs années car il ne tient pas compte des années bissextiles et donne donc des résultats inexacts. Voir le ticket Django # 19210 pour plus d'informations à ce sujet.Voici une solution pour trouver l'âge d'une personne en années, en mois ou en jours.
Disons que la date de naissance d'une personne est le 2012-01-17T00: 00: 00 Par conséquent, son âge au 2013-01-16T00: 00: 00 sera de 11 mois
ou s'il est né le 2012-12-17T00: 00: 00 , son âge le 2013-01-12T00: 00: 00 sera de 26 jours
ou s'il est né le 2000-02-29T00: 00: 00 , son âge le 2012-02-29T00: 00: 00 sera de 12 ans
Vous devrez importer datetime .
Voici le code:
Certaines fonctions supplémentaires utilisées dans les codes ci-dessus sont:
Et
Maintenant, nous devons alimenter get_date_format () avec les chaînes comme 2000-02-29T00: 00: 00
Il le convertira en objet de type date qui doit être alimenté par get_person_age (date_birth, date_today) .
La fonction get_person_age (date_birth, date_today) retournera age au format chaîne.
la source
Élargissement de la solution de Danny , mais avec toutes sortes de façons de signaler l'âge des jeunes (notez que c'est aujourd'hui
datetime.date(2015,7,17)
):Exemple de code:
la source
Comme je n'ai pas vu l'implémentation correcte, j'ai recodé le mien de cette façon ...
L'hypothèse d'être "18" le 28 février à la naissance le 29 est tout simplement erronée. Changer les limites peut être omis ... c'est juste une commodité personnelle pour mon code :)
la source
Extension à Danny W. Adair Answer , pour obtenir également le mois
la source
La date d'aujourd'hui
Ta date de naissance
Ton âge
la source
import date / heure
Dans ton cas:
la source
La solution de Danny légèrement modifiée pour une lecture et une compréhension plus faciles
la source