2009-04-19 4 views
96

나는 어떤 날짜 이후 몇 년 동안 있었는지 확인해야합니다. 현재 을 모듈에서 가져 왔으며 수년으로 변환하는 방법을 모르겠습니다.파이썬 timedelta 년

+3

이 응답을 참조하십시오 http://stackoverflow.com/a/9754466/65387을 – Adam

+0

관련 : [년을 변환하는 방법을 제 ] (http://stackoverflow.com/a/32658742/4279) – jfs

답변

111

몇 년이 지났는지 알려면 timedelta 이상이 필요합니다. 당신은 또한 시작 (또는 결말) 날짜를 알아야합니다. (윤년 일입니다.)

가장 좋은 방법은 dateutil.relativedeltaobject을 사용하는 것이지만 타사 모듈을 사용하는 것이 가장 좋습니다. 당신이 어떤 일로부터 n년했다 datetime이 (지금을 디폴트) 알고 싶은 경우에, 당신은 다음 ::

from dateutil.relativedelta import relativedelta 

def yearsago(years, from_date=None): 
    if from_date is None: 
     from_date = datetime.now() 
    return from_date - relativedelta(years=years) 

오히려 표준 라이브러리와 스틱 싶은 경우는, 답이있다 할 수있다 좀 더 복잡한 ::

2/29 및 18 년 전에는 2/29가 아니라면이 함수는 2/28을 반환합니다. 오히려 3/1를 돌려 줄 경우에, 다만 읽을 수있는 마지막 return 문을 변경 :

return from_date.replace(month=3, day=1, 
          year=from_date.year-years) 

귀하의 질문은 원래 당신이 어떤 날짜 이후에있었습니다 몇 년 알고 싶어했다. 당신이 년의 정수를 원하는 가정하면 연간 365.25 일을 기준으로 추측 할 수 다음 위 :이 스레드가 이미 죽었 비록

def num_years(begin, end=None): 
    if end is None: 
     end = datetime.now() 
    num_years = int((end - begin).days/365.25) 
    if begin > yearsago(num_years, end): 
     return num_years - 1 
    else: 
     return num_years 
+19

그레고리력에 대한 400 년 예외를 고려한 365.2425 (365.25 대신)로 완전히 정확할 수 있습니다. – brianary

+2

영국과 홍콩과 같은 국가에서는 3 월 1 일에 윤년이 "만료"되기 때문에 함수가 법적으로 중단됩니다. – antihero

+0

@brianary : 로컬 표준 시간대 ('datetime.now()'에 의해 소개 된 차이)가 * 평균 * 줄리안 ('365.25')과 그레고리오 (' '365.2425') 년.] (http://stackoverflow.com/a/32658742/4279). 올바른 접근법은 [@Adam Rosenfield의 대답] (http://stackoverflow.com/a/765862/4279) – jfs

0

얼마나 정확하게 필요합니까? 윤년이 걱정된다면 td.days/365.25 꽤 가까워 질 것입니다.

+0

나는 윤년에 대해 정말로 걱정하고있다. 18 세 이상인지 확인해야합니다. – Migol

+0

다음은 쉬운 한 줄 짜기가 아니라 두 날짜를 파싱해야하고 사람이 18 세 생일을 지났는지 아닌지를 알아야합니다. – eduffy

8

먼저 가장 상세한 수준에서 문제를 정확하게 해결할 수 없습니다. 년의 길이는 다양하며, 연도 길이에 대한 명확한 "올바른 선택"이 없습니다.

그렇다면 단위가 "자연스러운"단위 (아마 초 단위)가 무엇이든간에 그 차이를 얻고 그와 년 사이의 비율로 나눕니다. 예 :

delta_in_days/(365.25) 
delta_in_seconds/(365.25*24*60*60) 

... 또는 무엇이든간에. 그들이 몇 해보다 잘 정의되어 있지 않기 때문에 몇 달간 떨어져있어 라.

+1

서비스를받는 데 몇 년이 걸렸거나 특정 연령에 도달 한 사람의 질문 일 때 누군가가 의미하거나 사용하는 것이 아닙니다. –

+2

그레고리력의 400 년 예외를 고려하려면 365.25는 365.2425 여야합니다. – brianary

+1

글쎄, 문제는 * 정확하게 해결 될 수 있습니다 - 당신은 몇 년 전에 윤년이 있고 도약 할 수있는 시간을 미리 말할 수 있습니다. 몇 년, 그 다음 달, 그 다음 날 등을 빼기없이 매우 세련된 방법이 없다는 것입니다. – Litherum

42

누군가가 18 세인지 확인하려는 경우 윤년으로 인해 일부 가장자리의 경우에는 timedelta을 올바르게 사용하지 않습니다. 예를 들어 2000 년 1 월 1 일에 태어난 사람은 2018 년 1 월 1 일에 6575 일 후에 정확히 18 세가되며 (5 윤년 포함), 2001 년 1 월 1 일에 태어난 사람은 정확히 1 월 1 일에 정확히 6574 일 후에 18 세가됩니다. 2019 년 (4 윤년 포함). 따라서 누군가가 정확히 6574 일 된 경우, 자신의 생년월일에 대해 더 많은 정보를 알지 못해서 17 세 또는 18 세인지를 판단 할 수 없습니다.

올바른 방법은 날짜를 기준으로 나이를 직접 계산 한 다음 2 년을 빼고 현재 월/일이 출생 월/일보다 앞에있는 경우 1을 뺍니다.

+1

과 관련된 두 형식의 날짜 : [Age from python in birthday] (http : // stackoverflow. com/a/9754466/4279) – jfs

0

정의 yearsago 기능 중 하나를 사용하여 체크, 나는 제안 할 수 내가 직면하고 있던이 바로 그 문제에 대한 해결책을 제시한다.여기 (날짜의 형식은 DD-MM-YYYY 문자열입니다)입니다 :

def validatedate(date): 
    parts = date.strip().split('-') 

    if len(parts) == 3 and False not in [x.isdigit() for x in parts]: 
     birth = datetime.date(int(parts[2]), int(parts[1]), int(parts[0])) 
     today = datetime.date.today() 

     b = (birth.year * 10000) + (birth.month * 100) + (birth.day) 
     t = (today.year * 10000) + (today.month * 100) + (today.day) 

     if (t - 18 * 10000) >= b: 
      return True 

    return False 
0

이 기능은 ISO 형식의 문자열로 촬영 두 날짜 사이의 년의 차이를 (반환하지만 쉽게 사용하도록 수정 할 수 있습니다 어떤 형식이든)

import time 
def years(earlydateiso, laterdateiso): 
    """difference in years between two dates in ISO format""" 

    ed = time.strptime(earlydateiso, "%Y-%m-%d") 
    ld = time.strptime(laterdateiso, "%Y-%m-%d") 
    #switch dates if needed 
    if ld < ed: 
     ld, ed = ed, ld    

    res = ld[0] - ed [0] 
    if res > 0: 
     if ld[1]< ed[1]: 
      res -= 1 
     elif ld[1] == ed[1]: 
      if ld[2]< ed[2]: 
       res -= 1 
    return res 
-2

글쎄, 질문은 쉬운 것처럼 보입니다. '전체'연도의 수를 확인해야하며, 18에 해당하는 경우에만 월 및 일로 고생해야합니다. endDate.year - startDate.year == 18과 두 건으로 분할 : 가장자리 케이스는 당신이 며칠 확인해야 할 때, startDate.month != endDate.monthstartDate.month == endDate.month :

def isOfAge(birthDate, age=18): 
    endDate = date.today() 
    years = endDate.year - birthDate.year 
    if years == age: 
     return (birthDate.month < endDate.month or 
        (birthDate.month == endDate.month and birthDate.day < endDate.day))   
    return years > age 

그것은 여전히 ​​1 이상 라이너 람다하지만 여전히 꽤 짧은, 그리고 보인다 빠른 실행.

1
def age(dob): 
    import datetime 
    today = datetime.date.today() 

    if today.month < dob.month or \ 
     (today.month == dob.month and today.day < dob.day): 
     return today.year - dob.year - 1 
    else: 
     return today.year - dob.year 

>>> import datetime 
>>> datetime.date.today() 
datetime.date(2009, 12, 1) 
>>> age(datetime.date(2008, 11, 30)) 
1 
>>> age(datetime.date(2008, 12, 1)) 
1 
>>> age(datetime.date(2008, 12, 2)) 
0 
+0

2 월 29 일에 태어난 사람은 다음 2 월 28 일에 1 세가 된 것으로 간주됩니다. –

+0

"오늘 이후의 생일"에서 "오늘 전의 생일"로 반올림하여 29 세에 태어난 인구의 0.08 %를 수용하도록 수정되었습니다. 그게 해결 되니? –

+0

아니요, 해결되지 않습니다. 테스트를 믿지 않습니까? –

0

나는 Pyfdate

pyfdate은 무엇을 제안거야? 파이썬의 목표를 감안할 때

는 강력하고 사용하기 쉬운 스크립트 언어로, 날짜와 시간에 작업에 대한 기능은해야으로 사용자 친화적으로하지 않습니다. pyfdate의 목적은 에 대한 기능을 인 날짜와 시간으로 작업하여 Python의 나머지 부분 ( )으로 강력하고 사용하기 쉽게 처리하는 것입니다.

하지 여기에 언급 된 tutorial

1

또 다른 제 3 자 lib 디렉토리 mxDateTime (모두 파이썬 datetime 및 제 3 자 timeutil의 전신)는이 작업에 사용될 수 있습니다.

전술 yearsago

가 될 것이다 :

from mx.DateTime import now, RelativeDateTime 

def years_ago(years, from_date=None): 
    if from_date == None: 
     from_date = now() 
    return from_date-RelativeDateTime(years=years) 

첫번째 파라미터는 인스턴스 DateTime 것으로 예상된다. 1 마이크로 초 정밀도

def DT_from_dt_s(t): 
    return DT.DateTimeFromTicks(time.mktime(t.timetuple())) 

나이 :

당신이) 일초 정밀이를 사용할 수있는 일반 datetimeDateTime로 변환하는

def DT_from_dt_u(t): 
    return DT.DateTime(t.year, t.month, t.day, t.hour, 
    t.minute, t.second + t.microsecond * 1e-6) 

을 그리고 네,이 하나의 의존성을 추가 문제는 분명히 timeutil (Rick Copeland가 제안한)을 사용하는 것보다 과잉 공격이 될 것입니다.

3

일 수를 구한 다음 연도는 365.2425 (평균 그레고리력 연도)로 나눕니다. 몇 달 동안 30.436875 (평균 그레고리력 달)로 나눕니다.

1

마지막으로 가지고있는 것은 수학 문제입니다. 매 4 년마다 우리가 여분의 하루를 갖게되면, 365, 365 * 4 + 1이 아니라 4 일의 양을 줄 수있는 일을 시간표로 계산할 수 있습니다. 그런 다음 다시 4로 나눕니다. timedelta/((365 * 4) + 1)/4 = timedelta * 4/(365 * 4 일)

+0

년을 100으로 나눌 수있는 경우 윤년 문제는 적용되지 않습니다. 그래서 2000 년의 경우 - 그것은 4로 나눌 수 있기 때문에 도약해야하지만 ... - 백으로 나눌 수 있기 때문에 도약해서는 안되지만 ... - 400으로 나눌 수 있으므로 실제로 윤년이었습니다. 1900의 경우 : - 4로 나눌 수 있으므로 도약해야합니다. - 100으로 나눌 수 있으므로 뜀질해서는 안됩니다. - 400으로 나눌 수 없으므로이 규칙이 적용되지 않습니다. 1900 년은 윤년이 아니 었습니다. – Jblasco

1

이 내가 밖으로 일이 솔루션은 내가 ;-)

def menor_edad_legal(birthday): 
    """ returns true if aged<18 in days """ 
    try: 

     today = time.localtime()       

     fa_divuit_anys=date(year=today.tm_year-18, month=today.tm_mon, day=today.tm_mday) 

     if birthday>fa_divuit_anys: 
      return True 
     else: 
      return False    

    except Exception, ex_edad: 
     logging.error('Error menor de edad: %s' % ex_edad) 
     return True 
을 도울 수있는 희망입니다
5

여기에 생일을 계산하는 업데이트 DOB 기능입니다 같은 방법으로 인간이 수행

import datetime 
import locale 


# Source: https://en.wikipedia.org/wiki/February_29 
PRE = [ 
    'US', 
    'TW', 
] 
POST = [ 
    'GB', 
    'HK', 
] 


def get_country(): 
    code, _ = locale.getlocale() 
    try: 
     return code.split('_')[1] 
    except IndexError: 
     raise Exception('Country cannot be ascertained from locale.') 


def get_leap_birthday(year): 
    country = get_country() 
    if country in PRE: 
     return datetime.date(year, 2, 28) 
    elif country in POST: 
     return datetime.date(year, 3, 1) 
    else: 
     raise Exception('It is unknown whether your country treats leap year ' 
         + 'birthdays as being on the 28th of February or ' 
         + 'the 1st of March. Please consult your country\'s ' 
         + 'legal code for in order to ascertain an answer.') 
def age(dob): 
    today = datetime.date.today() 
    years = today.year - dob.year 

    try: 
     birthday = datetime.date(today.year, dob.month, dob.day) 
    except ValueError as e: 
     if dob.month == 2 and dob.day == 29: 
      birthday = get_leap_birthday(today.year) 
     else: 
      raise e 

    if today < birthday: 
     years -= 1 
    return years 

print(age(datetime.date(1988, 2, 29))) 
+0

dob가 2 월 29 일이고 현재 연도가 윤년이 아닐 때 이것은 중단됩니다. –