IT박스

몇 년 안에 파이썬 타임 델타

itboxs 2020. 7. 11. 11:08
반응형

몇 년 안에 파이썬 타임 델타


몇 년이 지난 지 몇 년이 지 났는지 확인해야합니다. 현재 모듈 timedelta에서 왔으며 datetime몇 년으로 변환하는 방법을 모르겠습니다.


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

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

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


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

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

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

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


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

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


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

여기에 언급되지 않은 다른 타사 라이브러리는이 작업에 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)

First parameter is expected to be a DateTime instance.

To convert ordinary datetime to DateTime you could use this for 1 second precision):

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

or this for 1 microsecond precision:

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)

And yes, adding the dependency for this single task in question would definitely be an overkill compared even with using timeutil (suggested by Rick Copeland).


In the end what you have is a maths issue. If every 4 years we have an extra day lets then dived the timedelta in days, not by 365 but 365*4 + 1, that would give you the amount of 4 years. Then divide it again by 4. timedelta / ((365*4) +1) / 4 = timedelta * 4 / (365*4 +1)


This is the solution I worked out, I hope can help ;-)

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

How exact do you need it to be? td.days / 365.25 will get you pretty close, if you're worried about leap years.


Even though this thread is already dead, might i suggest a working solution for this very same problem i was facing. Here it is (date is a string in the format 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

this function returns the difference in years between two dates (taken as strings in ISO format, but it can easily modified to take in any format)

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

I'll suggest Pyfdate

What is pyfdate?

Given Python's goal to be a powerful and easy-to-use scripting language, its features for working with dates and times are not as user-friendly as they should be. The purpose of pyfdate is to remedy that situation by providing features for working with dates and times that are as powerful and easy-to-use as the rest of Python.

the tutorial


Well, question seems rather easy. You need to check the number of 'full' years, and only if it's equal to 18 you need to bother with months and days. The edge case is: endDate.year - startDate.year == 18 and it splits to two cases: startDate.month != endDate.month and startDate.month == endDate.month, when you just have to check days:

 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

It's still more than one-liner-lambda, but it's still pretty short, and seems quick in execution.

참고URL : https://stackoverflow.com/questions/765797/python-timedelta-in-years

반응형