몇 년 안에 파이썬 타임 델타


답변:


156

timedelta몇 년이 지 났는지 알기 위해서는 a 이상이 필요합니다 . 시작일 (또는 종료일)도 알아야합니다. (이것은 윤년입니다.)

가장 좋은 방법은 dateutil.relativedelta object 를 사용하는 것이지만 타사 모듈입니다. 어떤 날짜로부터 몇 년 datetimen지 났는지 (기본값은 지금) 알고 싶다면 다음을 수행하십시오.

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)

표준 라이브러리를 고수하고 싶다면 대답이 조금 더 복잡합니다. :

from datetime import datetime
def yearsago(years, from_date=None):
    if from_date is None:
        from_date = datetime.now()
    try:
        return from_date.replace(year=from_date.year - years)
    except ValueError:
        # Must be 2/29!
        assert from_date.month == 2 and from_date.day == 29 # can be removed
        return from_date.replace(month=2, day=28,
                                 year=from_date.year-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 일을 기준으로 추측 한 다음 yearsago위에 정의 된 함수 중 하나를 사용하여 확인할 수 있습니다.

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

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

3
영국과 홍콩과 같은 국가에서는 윤년 동안 3 월 1 일로 "반올림"하기 때문에 귀하의 기능은 법적으로 중단됩니다.
antihero


3
또한 볼 두 시간에 대한 사실이 아니다 것들의 우수한 목록은 다음과 같습니다.
gvoysey

49

18 세 이상인지 확인하려는 timedelta경우 윤년으로 인해 일부 엣지 케이스에서 사용 이 제대로 작동하지 않습니다. 예를 들어 2000 년 1 월 1 일에 태어난 사람은 2018 년 1 월 1 일에 정확히 6575 일 후에 18 세가되고 (5 윤년 포함) 2001 년 1 월 1 일에 태어난 사람은 1 월 1 일에 정확히 6574 일 후에 18 세가됩니다. 2019 (4 년 윤년 포함). 따라서 누군가 정확히 6574 일이되었을 경우, 생년월일에 대한 약간의 정보를 모르면 17 세 또는 18 세인지 여부를 판단 할 수 없습니다.

이를 수행하는 올바른 방법은 2 년을 뺀 다음 현재 월 / 일이 출생 월 / 일보다 먼저 오면 날짜를 직접 계산하여 나이를 계산하는 것입니다.


9

먼저 가장 세부적인 수준에서 문제를 정확하게 해결할 수 없습니다. 연도는 다양하며 연도에 대한 명확한 "올바른 선택"은 없습니다.

즉, "자연"(아마 초) 단위의 차이를 얻고 그와 연도의 비율로 나눕니다. 예 :

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

...또는 무엇이든. 몇 년보다 잘 정의되어 있지 않기 때문에 몇 개월을 멀리하십시오.


2
그것은 몇 년 동안 서비스를 받았거나 특정 연령에 도달했는지에 대한 질문 일 때 누군가가 의미하거나 사용하는 것이 아닙니다.
John Machin

3
그레고리력을 400 년 예외로 간주하려면 365.25는 365.2425 여야합니다.
brianary

1
문제 올바르게 해결 될 있습니다. 윤년과 윤초 등을 몇 년인지 미리 알 수 있습니다. 단지 두 가지 형식의 날짜에서 연도, 월, 일 등을 빼지 않고 매우 우아한 방법이 없다는 것입니다
Litherum

7

다음은 업데이트 된 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)))

dob가 2 월 29 일이고 현재 연도가 윤년이 아닌 경우에 중단됩니다.
Trey Hunner

4

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


2
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

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

확인. 테스트를 "오늘 이후 생일"에서 "오늘 전 생일"으로 반전시켜 29 일에 태어난 인구의 0.08 %를 수용하도록 수정했습니다. 그게 해결됩니까?
John Mee

귀하의 예에 제대로 작동합니까!?! "today"를 2009 년 2 월 28 일로 설정하고 생년월일을 2008 년 2 월 29 일로 설정하면 적어도 0을 반환합니다. 제안한대로 1이 아닙니다 (Python 2.5.2). Machin을 무례하게 할 필요가 없습니다. 정확히 어떤 두 날짜에 문제가 있습니까?
John Mee

다시 시도하겠습니다. 2 월 29 일에 태어난 사람은 대부분의 법적 목적으로 2 월 28 일에 1 세가 된 것으로 간주됩니다. 코드는 "수정"전후에 0을 생성합니다. 실제로 두 버전의 코드는 모든 9 개의 입력 가능성 (월 <==> X 일 <==>)에 대해 정확히 동일한 출력을 생성합니다. BTW, 100.0 / (4 * 365 + 1)은 0.08이 아닌 0.068을 생성합니다.
John Machin

2
한숨. (0) 2 월 29 일 문제를 해결하는 것은 모든 날짜 산술에서 필수적입니다. 당신은 그것을 무시했습니다. (1) 귀하의 코드는 처음에는 나아지지 않았습니다. "정확히 동일한 결과를 생성"에서 무엇을 이해하지 못합니까? (2) today.month와 dob.month를 비교하는 세 가지 가능한 원자 결과 (<, ==,>); today.day와 dob.day를 비교하는 세 가지 가능한 원자 결과; 3 * 3 == 9 (3) stackoverflow.com/questions/2217488/…
John Machin

1

얼마나 정확해야합니까? td.days / 365.25윤년이 걱정된다면 아주 가까워 질 것입니다.


윤년이 정말 걱정됩니다. 사람이 18 세 이상인지 확인해야합니다.
Migol

그런 다음 쉬운 한 줄짜리가 없으므로 두 날짜를 구문 분석하고 18 세 생일을 지 났는지 여부를 파악해야합니다.
eduffy

1

여기에 언급되지 않은 다른 타사 라이브러리는이 작업에 mxDateTime (python datetime및 타사의 이전 버전 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인스턴스 일 것으로 예상됩니다 .

일반 datetime으로 변환하려면 DateTime1 초 정밀도로 이것을 사용할 수 있습니다)

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

또는 1 마이크로 초 정밀도의 경우 :

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가 제안한)을 사용하는 것보다 확실히 과잉 일 것입니다.


1

결국 당신이 가진 것은 수학 문제입니다. 4 년마다 하루가 더 있으면 타임 델타를 365 일이 아니라 365 * 4 + 1로 며칠 단위로 나눌 수 있습니다. 그러면 4 년이됩니다. 그런 다음 다시 4로 나눕니다. timedelta / ((365 * 4) +1) / 4 = timedelta * 4 / (365 * 4 +1)


연도는 400으로 나눌 수있는 경우를 제외하고 연도를 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

0

이 스레드가 이미 죽었더라도 내가 직면 한이 같은 문제에 대한 해결책을 제안 할 수 있습니다. 여기 있습니다 (날짜는 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

0

Pyfdate를 제안 하겠습니다

pyfdate 란 무엇입니까?

강력하고 사용하기 쉬운 스크립팅 언어라는 Python의 목표를 감안할 때 날짜와 시간을 다루는 기능은 사용자에게 친숙하지 않습니다. pyfdate의 목적은 다른 Python만큼 강력하고 사용하기 쉬운 날짜 및 시간으로 작업하기위한 기능을 제공하여 해당 상황을 해결하는 것입니다.

자습서


0
import datetime

def check_if_old_enough(years_needed, old_date):

    limit_date = datetime.date(old_date.year + years_needed,  old_date.month, old_date.day)

    today = datetime.datetime.now().date()

    old_enough = False

    if limit_date <= today:
        old_enough = True

    return old_enough



def test_ages():

    years_needed = 30

    born_date_Logan = datetime.datetime(1988, 3, 5)

    if check_if_old_enough(years_needed, born_date_Logan):
        print("Logan is old enough")
    else:
        print("Logan is not old enough")


    born_date_Jessica = datetime.datetime(1997, 3, 6)

    if check_if_old_enough(years_needed, born_date_Jessica):
        print("Jessica is old enough")
    else:
        print("Jessica is not old enough")


test_ages()

이것은 Carrousel 운영자가 Logan의 Run 영화에서 실행 한 코드입니다.)

https://ko.wikipedia.org/wiki/Logan%27s_Run_(film)


0

나는이 질문을 보았고 Adams가 가장 도움이된다는 것을 알았습니다. https://stackoverflow.com/a/765862/2964689

그러나 그의 방법에 대한 파이썬 예제는 없었지만 여기에 내가 사용한 것이 있습니다.

입력 : 날짜 / 시간 객체

출력 : 전체 연도의 정수 연령

def age(birthday):
    birthday = birthday.date()
    today = date.today()

    years = today.year - birthday.year

    if (today.month < birthday.month or
       (today.month == birthday.month and today.day < birthday.day)):

        years = years - 1

    return years

0

존 미 (John Mee)의 단순성에 대한 솔루션이 마음에 들었고, 윤년이 아닌 2 월 28 일 또는 3 월 1 일에 2 월 29 일에 태어난 사람들의 나이를 결정하는 방법에 대해서는 걱정하지 않습니다. 그러나 여기에 그의 코드가 약간 수정되었습니다 나는 불만을 해결한다고 생각합니다.

def age(dob):
    import datetime
    today = datetime.date.today()
    age = today.year - dob.year
    if ( today.month == dob.month == 2 and
         today.day == 28 and dob.day == 29 ):
         pass
    elif today.month < dob.month or \
      (today.month == dob.month and today.day < dob.day):
        age -= 1
    return age
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.