Câu trả lời:
Điều đó có thể được thực hiện đơn giản hơn nhiều khi xem int (True) là 1 và int (Sai) là 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()
trả về ngày trong múi giờ địa phương có thể khác với nơi sinh. Bạn có thể cần phải sử dụng các múi giờ một cách rõ ràng
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
Cập nhật: Sử dụng giải pháp của Daniel , tốt hơn
except
khối của bạn chỉ nên bắt một ngoại lệ cụ thể có thể được nêu ra.
ValueError
. Cập nhật.
def calculate_age(dob)
datetime.date(2014, 1, 1)
cho -1, nó sẽ cho 0. Bạn today > dob
đang kiểm tra xem DOB có trong quá khứ không, không sớm hơn cùng năm. datetime.date.today()
bao gồm thông tin năm, đó là lý do tại sao tôi thay thế nó bằng năm hiện tại trong giải pháp của mình.
from datetime import date
days_in_year = 365.2425
age = int((date.today() - birth_date).days / days_in_year)
Trong Python 3, bạn có thể thực hiện phép chia trên datetime.timedelta
:
from datetime import date, timedelta
age = (date.today() - birth_date) // timedelta(days=365.2425)
365.25
) và Gregorian năm dương lịch ( 365.2425
) là ít hơn một ngày nếu bạn sống dưới 130 năm.
(date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425)
nên trả lại 13
, nhưng nó sẽ trả về 12
. Không có người yêu, kết quả là 12.999582469181433
.
Theo đề xuất của @ [Tomasz Zielinski] và @Williams python-dateutil có thể làm điều đó chỉ 5 dòng.
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)`
Cách đơn giản nhất là sử dụng 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
Thật không may, bạn không thể chỉ sử dụng timedelata vì đơn vị lớn nhất mà nó sử dụng là ngày và năm nhuận sẽ khiến bạn tính toán không hợp lệ. Do đó, hãy tìm số năm sau đó điều chỉnh theo một năm nếu năm ngoái không đầy đủ:
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
Cập nhật:
Giải pháp này thực sự gây ra một ngoại lệ khi ngày 29 tháng 2 đi vào hoạt động. Đây là kiểm tra chính xác:
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
Cập nhật2:
Gọi nhiều cuộc gọi đến now()
một hit hiệu suất là vô lý, nó không quan trọng trong tất cả nhưng trường hợp cực kỳ đặc biệt. Lý do thực sự để sử dụng một biến là nguy cơ không thống nhất dữ liệu.
Gotcha cổ điển trong kịch bản này là những gì cần làm với những người sinh vào ngày 29 tháng 2. Ví dụ: bạn cần đủ 18 tuổi để bỏ phiếu, lái xe, mua rượu, v.v ... nếu bạn sinh vào ngày 2004-2-29, ngày đầu tiên bạn được phép làm những việc đó là gì: 2022-02 -28, hoặc 2022-03-01? AFAICT, chủ yếu là người đầu tiên, nhưng một vài killjoy có thể nói điều sau.
Đây là mã phục vụ cho 0,068% (xấp xỉ) dân số sinh vào ngày đó:
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
Đây là đầu ra:
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
Nếu bạn đang tìm cách in cái này trong một trang bằng các mẫu django, thì những điều sau đây có thể là đủ:
{{ birth_date|timesince }}
|timesince
để tính toán thời gian trong nhiều năm vì nó không tính đến năm nhuận và do đó mang lại kết quả không chính xác. Xem vé Django # 19210 để biết thêm thông tin về điều này.
Đây là một giải pháp để tìm tuổi của một người là năm hoặc tháng hoặc ngày.
Giả sử ngày sinh của một người là 2012-01-17T00: 00: 00 Do đó, tuổi của anh ấy vào 2013-01-16T00: 00: 00 sẽ là 11 tháng
hoặc nếu anh ấy sinh vào ngày 2012-12-17T00: 00: 00 , tuổi của anh ấy vào 2013-01-12T00: 00: 00 sẽ là 26 ngày
hoặc nếu anh ấy sinh vào 2000-02-29T00: 00: 00 , tuổi của anh ấy vào 2012 / 02-29T00 : 00: 00 sẽ là 12 năm
Bạn sẽ cần nhập datetime .
Đây là mã:
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
Một số chức năng bổ sung được sử dụng trong các mã trên là:
def get_todays_date():
"""
This function returns todays date in proper date object format
"""
return datetime.now()
Và
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")
Bây giờ, chúng ta phải cung cấp get_date_format () với các chuỗi như 2000-02-29T00: 00: 00
Nó sẽ chuyển đổi nó thành đối tượng loại ngày sẽ được cung cấp cho get_person_age (date_birth, date_today) .
Hàm get_person_age (date_birth, date_today) sẽ trả về tuổi ở định dạng chuỗi.
Mở rộng về Giải pháp của Daniel , nhưng với đủ mọi cách để báo cáo độ tuổi cho dân gian trẻ hơn (lưu ý, ngày nay là 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'
Mã mẫu:
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
Vì tôi không thấy cách thực hiện chính xác, tôi đã mã hóa lại theo cách này ...
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)
Giả định là "18" vào ngày 28 tháng 2 khi sinh vào ngày 29 là sai. Hoán đổi giới hạn có thể bị bỏ qua ... đó chỉ là sự thuận tiện cá nhân cho mã của tôi :)
Mở rộng cho Daniel W. Adair Trả lời , để có được tháng
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
nhập thời gian
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
Trong trường hợp của bạn:
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
Giải pháp thay đổi một chút của Daniel để dễ đọc và dễ hiểu hơn
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
mô-đun tiêu chuẩn là không đủ, bạn có thể thử: labix.org/python-dateutil