199 votes

Âge à partir de la date de naissance en python

Comment puis-je trouver un âge en python à partir de la date du jour et de la date de naissance d'une personne ? La date de naissance provient d'un DateField dans un modèle Django.

4 votes

Lorsque la norme datetime n'est pas suffisant, vous pouvez essayer : labix.org/python-dateutil

1 votes

Cela a presque certainement été résolu par : dateutil.relativedelta.relativedelta

382voto

Danny W. Adair Points 2914

Cela peut être fait beaucoup plus simplement en considérant que int(True) vaut 1 et int(False) vaut 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))

8 votes

Un point de détail : date.today() renvoie la date dans le fuseau horaire local qui peut être différent de celui du lieu de naissance. Vous devrez peut-être utiliser les fuseaux horaires de manière explicite

20 votes

Cela dépend probablement de votre définition de l'"âge". À toutes fins utiles, un anniversaire est généralement donné sous la forme d'une date, et non d'un fuseau horaire (c'est-à-dire que "né" manque les détails). La plupart des gens ne sont pas nés à minuit pile (donc ils fêtent leur anniversaire prématurément :-)), et lorsqu'ils se trouvent dans un autre fuseau horaire, je suppose que la plupart des gens fêtent leur anniversaire à l'heure locale (c'est ce que je fais, je vis 10-12h en avance sur l'heure de mon lieu de naissance). Si "born" était une date qui tient compte du fuseau horaire, vous pourriez utiliser l'arithmétique de pytz et normalize() - peut-être intéressant pour un logiciel d'astrologie ?

2 votes

Je suis tout à fait 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 célèbre 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.

70voto

Mark Points 49079
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

Mise à jour : Utilisez La solution de Danny c'est mieux

2 votes

Par principe, votre except ne devrait attraper que la seule exception spécifique qui pourrait être soulevée.

1 votes

@Daenyth : Bon appel... Je pense que c'est un ValueError . Mis à jour.

0 votes

Je vais même jusqu'à tester le message de l'exception pour m'assurer qu'il correspond à 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 celle que vous attendez.

19voto

Ramin Points 2528
from datetime import date

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

En Python 3, vous pouviez effectuer une division sur datetime.timedelta :

from datetime import date, timedelta

age = (date.today() - birth_date) // timedelta(days=365.2425)

2 votes

Chaque quatrième année est une année bissextile sauf chaque centième année n'est pas une année bissextile sauf chaque quatre centième année est une année bissextile. essayez days_in_year=365.2425

3 votes

@Dan : la différence entre Julian ( 365.25 ) et l'année civile grégorienne ( 365.2425 ) est inférieure à un jour si vous vivez moins de 130 ans.

5 votes

Cela ne fonctionne pas pour un peu de dates : (date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425) devrait retourner 13 mais il renvoie 12 . Sans surprise, le résultat est 12.999582469181433 .

13voto

user1569050 Points 754

La méthode la plus simple consiste à utiliser 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

9 votes

Cela ne fonctionne pas correctement lorsque la date d'anniversaire est le 29 février et que la date d'aujourd'hui est le 28 février (il agira comme si aujourd'hui était le 29 février).

5voto

Alex Lebedev Points 4273

Malheureusement, vous ne pouvez pas simplement utiliser timedelata car la plus grande unité qu'il utilise est le jour et les années bissextiles rendront vos calculs invalides. Par conséquent, trouvons le nombre d'années puis ajustons d'une unité si la dernière année n'est pas complète :

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

Mise à jour :

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.year
if all((x >= y) for x,y in zip(today.timetuple(), birth_date.timetuple()):
   age = years
else:
   age = years - 1

Mise à jour 2 :

L'appel multiple à now() une baisse de performance est ridicule, cela n'a aucune importance sauf dans des cas extrêmement particuliers. La véritable raison d'utiliser une variable est le risque d'incohérence des données.

0 votes

Merci, j'ai découvert cela en faisant quelques tests - et j'ai abouti à un code similaire trouvé sur le lien d'AndiDog.

3 votes

Strike 1 : Vous utilisez datetime.datetime au lieu de datetime.date. Strike 2 : Votre code est laid et inefficace. Appeler datetime.now() THREE temps ? Strike 3 : La date de naissance 29 Feb 2004 et la date du jour 28 Feb 2010 devraient retourner l'âge 6, et non mourir en criant "ValueError : day is out of range for month". C'est fini !

0 votes

Désolé, votre code "Upd" est encore plus baroque et cassé que la première tentative -- rien à voir avec le 29 février ; il échoue dans de NOMBREUX cas simples comme 2009-06-15 à 2010-07-02 ... la personne a manifestement un peu plus d'un an mais vous déduisez une année parce que le test sur les jours (2 >= 15) échoue. Et il est évident que vous ne l'avez pas testé - il contient une erreur de syntaxe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X