파이썬에서 생년월일


159

오늘 날짜에서 파이썬 연령을 어떻게 알 수 있습니까? 생년월일은 Django 모델의 DateField에서 가져온 것입니다.


4
표준 datetime모듈로 충분하지 않은 경우 시도해 볼 수 있습니다. labix.org/python-dateutil
Tomasz Zieliński

1
이것은 거의 확실하게 해결되었습니다 :dateutil.relativedelta.relativedelta
Williams

답변:


288

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))

4
nitpick : date.today()출생지와 다를 수있는 현지 시간대의 날짜를 반환합니다. 시간대를 명시 적으로 사용해야
jfs

10
그것은 아마도 당신의 "나이"에 대한 정의에 달려 있습니다. 모든 실제적인 목적으로 생일은 일반적으로 시간대를 인식하는 날짜 시간이 아닌 날짜로 제공됩니다 (예 : "출생"에 세부 사항이 누락 됨). 대부분의 사람들은 자정에 날카롭게 태어나지 않으며 (따라서 보통 :-) 관찰합니다. 다른 시간대에있을 때, 대부분의 사람들이 현지 시간에 생일을 관찰한다고 가정합니다. 출생지 시간). "born"이 시간대 인식 날짜 시간 인 경우 pytz의 산술 및 normalize ()를 사용할 수 있습니다. 점성술 소프트웨어에 관심이 있습니까?
Danny W. Adair

2
나는 인간의 맥락에서 완전히 동의하지만 당신의 공식은 더 넓은 맥락에서 사용될 수 있습니다. 비록 가족의 전통과 프로그래머이기 때문에 1 시간 더 일찍 생일을 축하하지는 않지만 내가 어디에 있든 시간을 계산하는 것은 사소한 일입니다.
jfs

@pyd : born is date / datetime
kjagiello

68
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

업데이트 : 사용 대니의 솔루션은 , 그것은 더 나은


2
원칙적으로 except블록은 발생할 수있는 하나의 특정 예외 만 포착해야합니다.
Daenyth

1
@Daenyth : 좋은 전화 ... 나는 생각합니다 ValueError. 업데이트되었습니다.
mpen

나는 심지어 예외 메시지를 테스트하여 내가 기대하는 것을 확인합니다. 위의 코드를 사용하더라도 ValueError가 발생할 가능성이 있지만 예상 한 ValueError는 아닙니다.
랜디 Syring

+ 예외이지만 내 문제가 있습니까? 나는 그것이 매우 간단하다고 생각합니다. def calculate_age(dob)
Grijesh Chauhan

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)

파이썬 3에서는 다음과 같이 나눌 수 있습니다 datetime.timedelta.

from datetime import date, timedelta

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

2
매 4 년마다 윤년을 제외하고 윤년이 아닌 윤년을 제외하고 윤년입니다. try days_in_year = 365.2425
Dan

3
@ 단 : 줄리안 ( 365.25)과 그레고리력 연도 ( 365.2425)의 차이는 130 세 미만인 경우 하루보다 짧습니다.
jfs

4
일부 날짜 에는 작동하지 않습니다 . (date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425)should return 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)`

10

가장 간단한 방법은 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

7
생일이 2 월 29 일이고 오늘 날짜가 2 월 28 일이면 오늘이 2 월 29 일인 것처럼 작동합니다.
Trey Hunner

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 -= 1
    return y

날짜 인스턴스 또는 그와 같은 일부 객체, docs.python.org/3/library/datetime.html#datetime.date, 오타가 수정되었습니다.
gzerone

5

불행히도, 사용하는 가장 큰 단위는 일이며 윤년으로 인해 계산이 유효하지 않기 때문에 타임 델라 타를 사용할 수 없습니다. 따라서 지난 해가 가득 차 있지 않은 경우 몇 년을 찾은 다음 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

Upd :

이 솔루션은 29 년 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()성능 저하 에 대해 여러 번의 전화를 거는 것은 우스운 일이지만, 매우 특별한 경우는 아닙니다. 변수를 사용해야하는 실제 이유는 데이터 불일치의 위험 때문입니다.


고마워, 나는 몇 가지 테스트를 통해 이것을 알았고 AndiDog의 링크에서 찾은 비슷한 코드를 만들었습니다.
tkalve

3
경고 1 : datetime.date 대신 datetime.datetime을 사용하고 있습니다. Strike 2 : 코드가보기 흉하고 비효율적입니다. datetime.now () 호출 번 ?? 파업 3 : 2004 년 2 월 29 일과 오늘 날짜 인 2010 년 2 월 28 일은 "ValueError : day is range of range of range"(이하의 월이 범위를 벗어남)로 소리 지르지 않고 6 세가되어야합니다. 당신은 밖으로!
John Machin 2019

죄송합니다. "Upd"코드는 첫 번째 시도보다 훨씬 더 바로크하고 손상되었습니다. 2 월 29 일과 관련이 없습니다. 그것은 2009-06-15에서 2010-07-02와 같은 많은 간단한 경우에 실패합니다 ... 사람은 분명히 1 세가 약간 넘지 만 일 (2> = 15)의 테스트가 실패하기 때문에 1 년을 공제합니다. 그리고 분명히 테스트하지 않았습니다. 구문 오류가 포함되어 있습니다.
John Machin

4

이 시나리오의 고전은 2 월 29 일에 태어난 사람들과 관계가 있습니다. 예 : 투표, 자동차 운전, 음주 등을하려면 18 세 이상이어야합니다. 2004-02-29 년에 태어난 경우 첫 번째 날은 다음과 같습니다. 2022-02 -28 또는 2022-03-01? AFAICT, 주로 첫 번째이지만, 몇 가지 살인이 후자를 말할 수 있습니다.

다음은 그 날에 태어난 인구의 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

그리고 최근에 도약 에 대해 배웠습니다 .
Bobort

3

django 템플릿을 사용하여 페이지에서 이것을 인쇄하려면 다음과 같이 충분할 수 있습니다.

{{ birth_date|timesince }}

4
|timesince윤년을 설명하지 않으므로 결과가 부정확하기 때문에 장고를 수년에 걸친 타임 델타 계산에 사용하지 마십시오 . 이에 대한 자세한 내용은 Django 티켓 # 19210을 참조하십시오.
jnns

몰랐어요 감사.
Anoyz

2

다음은 사람의 나이를 몇 년 또는 몇 달 또는 몇 일로 찾는 솔루션입니다.

사람의 생년월일이 2012-01-17T00 : 00 : 00이라고 가정 하면 2013-01-16T00 : 00 : 00의 나이 는 11 개월입니다.

그가 태어난 경우 또는 00 : 2012-12-17T00 00 , 그의 나이 2013-01-12T00 : 00 : 00이 될 것입니다 이십육일

또는 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")

이제 2000-02-29T00 : 00 : 00 과 같은 문자열로 get_date_format () 을 공급해야합니다 .

get_person_age (date_birth, date_today)에 공급할 날짜 유형 객체로 변환합니다 .

get_person_age (date_birth, date_today) 함수 는 연령을 문자열 형식으로 반환합니다.


2

Danny의 솔루션을 확장 하지만 젊은 사람들의 연령을보고하는 모든 종류의 방법으로 (오늘은 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

1

올바른 구현을 보지 못했지만이 방법으로 코드를 코딩했습니다 ...

    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)

29 일에 태어 났을 때 2 월 28 일에 "18"이라는 가정은 잘못되었습니다. 경계를 바꾸는 것은 생략 될 수 있습니다 ... 내 코드의 개인적인 편의 일뿐입니다 :)



1
import datetime

오늘 날짜

td=datetime.datetime.now().date() 

생년월일

bd=datetime.date(1989,3,15)

나이

age_years=int((td-bd).days /365.25)

0

날짜 / 시간 가져 오기

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

0

더 쉽게 읽고 이해하기 위해 약간 수정 된 Danny의 솔루션

    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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.