回答:
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))
date.today()
出身地とは異なる可能性があるローカルタイムゾーンの日付を返します。タイムゾーンを明示的
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
更新:ダニーのソリューションを使用してください、それはより良いです
except
ブロックは発生する可能性のある特定の例外を1つだけキャッチする必要があります。
ValueError
。更新しました。
def calculate_age(dob)
datetime.date(2014, 1, 1)
-1を与えると、0を与えるはずtoday > dob
です。DOBが過去にあるかどうかを確認しています。同じ年の初めではありません。datetime.date.today()
年情報が含まれているため、ソリューションで現在の年に置き換えます。
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)
365.25
)とグレゴリオ暦の年(365.2425
)の差は、130歳未満の場合、1日未満です。
(date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425)
必要13
がありますが、を返します12
。フローリングされていない場合、結果は12.999582469181433
です。
@ [Tomasz Zielinski]と@Williamsが提案するように、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)`
最も簡単な方法は 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を使用することはできません。最大の単位は日であり、うるう年は計算を無効にするためです。したがって、年数を見つけて、最後の年がいっぱいでない場合は1で調整します。
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
更新:
このソリューションは、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()
パフォーマンスヒットへの複数の呼び出しはばかげています。非常に特殊な場合を除いて、それはすべて問題ではありません。変数を使用する本当の理由は、データの不整合のリスクです。
このシナリオの古典的な落とし穴は、2月29日に生まれた人々をどうするかです。例:投票、車の運転、アルコールの購入などを行うには、18歳である必要があります... 2004-02-29で生まれた場合、そのようなことを行うことが許可されている最初の日は次のとおりです:2022-02 -28、または2022-03-01?AFAICT、ほとんどが最初ですが、いくつかのkilljoysは後者を言うかもしれません。
その日に生まれた人口の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
これをdjangoテンプレートを使用してページに印刷する場合は、次の方法で十分です。
{{ birth_date|timesince }}
|timesince
うるう年は考慮されないため、不正確な結果が生じるため、Djangoを使用して数年にわたるtimedeltaを計算しないでください。詳細については、Djangoチケット#19210を参照してください。
これは、人の年齢を年、月、または日で見つけるためのソリューションです。
人の生年月日が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歳になります。
datetimeをインポートする必要があります。
これがコードです:
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
上記のコードで使用されるいくつかの追加機能は次のとおりです。
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")
ここで、get_date_format()に2000-02-29T00:00:00のような文字列をフィードする必要があります。
それをget_person_age(date_birth、date_today)に供給される日付型オブジェクトに変換します。
関数get_person_age(date_birth、date_today)は、年齢を文字列形式で返します。
ダニーのソリューションを拡張しますが、若い人々の年齢を報告するためのあらゆる種類の方法を使用します(注、今日はです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
私は正しい実装を見なかったので、私はこのように私のコードを書き直しました...
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」であるという仮定は間違っています。境界のスワッピングは省略できます...これは私のコードの個人的な利便性にすぎません:)
Danny W. Adair Answerまで拡張して、月も取得します
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
インポート日時
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
読みやすく、理解しやすいように少し変更したダニーのソリューション
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
datetime
、モジュールが十分ではありません、あなたが試すことができます:labix.org/python-dateutil