Придира: date.today()возвращает дату в местном часовом поясе, которая может отличаться от места рождения. Возможно, вам придется использовать часовые пояса явно
JFS
10
Это, вероятно, зависит от вашего определения «возраст». Во всех практических целях день рождения обычно указывается как дата, а не как дата / время с учетом часового пояса (т. Е. «Рожденный» пропускает детали). Большинство людей не рождаются ровно в полночь (поэтому обычно наблюдают преждевременно :-)), и когда я нахожусь в другом часовом поясе, я предполагаю, что большинство людей отмечают свой день рождения по местному времени (это то, что я делаю, я живу на 10-12 часов вперед моего места рождения). Если бы «рожденный» был датой времени с учетом часового пояса, вы могли бы использовать арифметику pytz и normalize () - может быть, это интересно для астрологического программного обеспечения?
Дэнни В. Адэйр
2
Я полностью согласен в контексте человеческих возрастов, но ваша формула может быть использована в более широком контексте. Хотя я лично никогда не отмечаю свой день рождения даже на час раньше из-за семейных традиций и, будучи программистом, легко вычислить время, где бы я ни был.
JFS
@pyd: родился - это дата / дата / время
kjagiello
68
from datetime import date
def 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
В принципе, ваш exceptблок должен отлавливать только одно конкретное исключение, которое можно вызвать.
Дейнит
1
@Daenyth: хороший звонок ... я думаю, что это ValueError. Обновлено.
mpen
Я даже дошел до того, что проверил сообщение об исключении, чтобы убедиться, что оно того, чего я ожидаю. Даже с приведенным выше кодом есть вероятность, что выдается ошибка ValueError, но это не та ошибка ValueError, которую вы ожидаете.
Рэнди Сайринг,
+ за исключением но, есть ли проблема в моем ? Я думаю, что это довольно просто. def calculate_age(dob)
Грижеш Чаухан
1
@GrijeshChauhan: Да, ваш не работает. datetime.date(2014, 1, 1)дает -1, должно давать 0. Вы today > dobпроверяете, есть ли DOB в прошлом, а не ранее в этом же году. datetime.date.today()включает в себя информацию о году, поэтому я заменяю ее текущим годом в своем решении.
mpen
18
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)
каждый четвертый год является високосным, за исключением того, что каждый сотый год не является високосным, за исключением того, что каждый четвертый год является високосным. попробуй days_in_year = 365,2425
Дан
3
@Dan: разница между юлианским ( 365.25) и григорианским календарным годом ( 365.2425) составляет менее суток, если вы живете менее 130 лет.
JFS
4
Это не работает для некоторых дат: (date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425)должен вернуться 13, но он возвращается 12. Без цвета, результат есть 12.999582469181433.
href_
13
По предложению @ [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
Это не работает правильно, когда день рождения 29 февраля, а сегодняшняя дата 28 февраля (будет действовать так, как если бы сегодня было 29 февраля).
Трей Ханнер
6
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 -=1return y
экземпляр даты или что-то подобное, docs.python.org/3/library/datetime.html#datetime.date, опечатка исправлена.
гзероне
5
К сожалению, вы не можете просто использовать timedelata, поскольку наибольшая единица, которую он использует, это день, а високосные годы сделают ваши вычисления недействительными. Поэтому давайте найдем количество лет, а затем скорректируем его на единицу, если последний год не был полным:
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:
Это решение действительно вызывает исключение, когда 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()хитом производительности нелепо, это не имеет значения во всех случаях, кроме крайне особых случаев. Настоящей причиной использования переменной является риск несогласованности данных.
Спасибо, я узнал об этом, выполнив несколько тестов, и в результате получил похожий код, найденный по ссылке AndiDog.
tkalve
3
Удар 1. Вы используете datetime.datetime вместо datetime.date. Удар 2: Ваш код уродлив и неэффективен. Вызов datetime.now () три раза ?? Забастовка 3: дата рождения 29 февраля 2004 г. и сегодняшняя дата 28 февраля 2010 г. должны вернуть возраст 6, а не вопить «ValueError: день вне диапазона для месяца». Вы вышли!
Джон Мачин
Извините, ваш код "Upd" еще более барочный и сломанный, чем первая попытка - ничего общего с 29 февраля; он терпит неудачу в МНОГИХ простых случаях, таких как 2009-06-15 - 2010-07-02 ... человеку, очевидно, немногим более 1 года, но вы вычитаете год, потому что тест в дни (2> = 15) не пройден. И, очевидно, вы не проверяли его - он содержит синтаксическую ошибку.
Джон Мачин
4
Классическая ошибка в этом сценарии заключается в том, что делать с людьми, рожденными 29 февраля. Пример: вам нужно быть в возрасте 18 лет, чтобы голосовать, водить машину, покупать алкоголь и т. Д. ... если вы родились 2004-02-29, то в какой первый день вам разрешено делать такие вещи: 2022-02 -28 или 2022-03-01? AFAICT, в основном первый, но несколько убийств могут сказать последнее.
Вот код, который обслуживает 0,068% (приблизительно) населения, родившегося в этот день:
Не используйте Django |timesinceдля расчета временной дельты за несколько лет, потому что она не учитывает високосные годы и, следовательно, дает неточные результаты. Смотрите Django билет # 19210 для получения дополнительной информации об этом.
jnns
Не знал этого. Спасибо.
Анойз
2
Вот решение, чтобы найти возраст человека в годах, месяцах или днях.
Допустим, дата рождения человека 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 лет
Вам нужно будет импортировать дату и время .
Вот код:
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
Некоторые дополнительные функции, используемые в приведенных выше кодах:
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: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'
Образец кода:
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
Так как я не видел правильную реализацию, я перекодировал мою таким образом ...
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)
Предположение о том, что 28-го февраля "18", когда он родился 29-го февраля, просто неверно. Обмен границ может быть опущен ... это просто личное удобство для моего кода :)
Слегка измененное решение Дэнни для облегчения чтения и понимания
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
модуля недостаточно, вы можете попробовать: labix.org/python-dateutildateutil.relativedelta.relativedelta
Ответы:
Это можно сделать намного проще, учитывая, что int (True) равно 1, а int (False) равно 0:
источник
date.today()
возвращает дату в местном часовом поясе, которая может отличаться от места рождения. Возможно, вам придется использовать часовые пояса явноОбновление: используйте решение Дэнни , это лучше
источник
except
блок должен отлавливать только одно конкретное исключение, которое можно вызвать.ValueError
. Обновлено.def calculate_age(dob)
datetime.date(2014, 1, 1)
дает -1, должно давать 0. Выtoday > dob
проверяете, есть ли DOB в прошлом, а не ранее в этом же году.datetime.date.today()
включает в себя информацию о году, поэтому я заменяю ее текущим годом в своем решении.В Python 3 вы можете выполнить деление на
datetime.timedelta
:источник
365.25
) и григорианским календарным годом (365.2425
) составляет менее суток, если вы живете менее 130 лет.(date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425)
должен вернуться13
, но он возвращается12
. Без цвета, результат есть12.999582469181433
.По предложению @ [Tomasz Zielinski] и @Williams python-dateutil может сделать это всего за 5 строк.
источник
Самый простой способ - это использование
python-dateutil
источник
источник
К сожалению, вы не можете просто использовать timedelata, поскольку наибольшая единица, которую он использует, это день, а високосные годы сделают ваши вычисления недействительными. Поэтому давайте найдем количество лет, а затем скорректируем его на единицу, если последний год не был полным:
UPD:
Это решение действительно вызывает исключение, когда 29 февраля вступает в игру. Вот правильная проверка:
UPD2:
Называть несколько вызовов
now()
хитом производительности нелепо, это не имеет значения во всех случаях, кроме крайне особых случаев. Настоящей причиной использования переменной является риск несогласованности данных.источник
Классическая ошибка в этом сценарии заключается в том, что делать с людьми, рожденными 29 февраля. Пример: вам нужно быть в возрасте 18 лет, чтобы голосовать, водить машину, покупать алкоголь и т. Д. ... если вы родились 2004-02-29, то в какой первый день вам разрешено делать такие вещи: 2022-02 -28 или 2022-03-01? AFAICT, в основном первый, но несколько убийств могут сказать последнее.
Вот код, который обслуживает 0,068% (приблизительно) населения, родившегося в этот день:
Вот вывод:
источник
Если вы хотите напечатать это на странице с использованием шаблонов django, тогда может быть достаточно следующего:
источник
|timesince
для расчета временной дельты за несколько лет, потому что она не учитывает високосные годы и, следовательно, дает неточные результаты. Смотрите 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 лет
Вам нужно будет импортировать дату и время .
Вот код:
Некоторые дополнительные функции, используемые в приведенных выше кодах:
И
Теперь мы должны передать 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)
):Образец кода:
источник
Так как я не видел правильную реализацию, я перекодировал мою таким образом ...
Предположение о том, что 28-го февраля "18", когда он родился 29-го февраля, просто неверно. Обмен границ может быть опущен ... это просто личное удобство для моего кода :)
источник
Расширьте до Дэнни В. Адэйра Ответа , чтобы получить также месяц
источник
Сегодняшняя дата
Ваша дата рождения
Ваш возраст
источник
дата импорта время
В твоем случае:
источник
Слегка измененное решение Дэнни для облегчения чтения и понимания
источник