Python timedelta в течение многих лет

Используйте QueryBuider для создания запроса для ActiveDataProvider и используйте «Объединение» и псевдонимы полей для результатов объединения из разных таблиц с одинаковыми именами, например так:

124
задан Migol 19 April 2009 в 21:36
поделиться

12 ответов

Вам нужно больше timedelta , чтобы сказать, сколько лет прошло; Вам также нужно знать дату начала (или окончания). (Это високосный год.)

Лучше всего использовать объект dateutil.relativedelta , но это сторонний модуль. Если вы хотите узнать datetime , который был n лет от некоторой даты (по умолчанию прямо сейчас), вы можете сделать следующее ::

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
146
ответ дан 24 November 2019 в 01:07
поделиться

Насколько он вам нужен? td.days / 365.25 сблизит вас, если вы беспокоитесь о високосных годах.

1
ответ дан 24 November 2019 в 01:07
поделиться

Прежде всего, на самом детальном уровне проблема не может быть решена точно. Годы различаются по длине, и не существует четкого «правильного выбора» для длины года.

Тем не менее, получите разницу в единицах, которые являются «естественными» (вероятно, в секундах), и разделите на соотношение между этим и годами. Например,

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

... или что угодно. Держитесь подальше от месяцев, так как они еще менее четко определены, чем годы.

9
ответ дан 24 November 2019 в 01:07
поделиться

If you're trying to check if someone is 18 years of age, using timedelta will not work correctly on some edge cases because of leap years. For example, someone born on January 1, 2000, will turn 18 exactly 6575 days later on January 1, 2018 (5 leap years included), but someone born on January 1, 2001, will turn 18 exactly 6574 days later on January 1, 2019 (4 leap years included). Thus, you if someone is exactly 6574 days old, you can't determine if they are 17 or 18 without knowing a little more information about their birthdate.

The correct way to do this is to calculate the age directly from the dates, by subtracting the two years, and then subtracting one if the current month/day precedes the birth month/day.

46
ответ дан 24 November 2019 в 01:07
поделиться

Даже если этот поток уже мертв, могу ли я предложить рабочее решение для той же самой проблемы i столкнулся. Вот она (дата - строка в формате дд-мм-гггг):

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
ответ дан 24 November 2019 в 01:07
поделиться

эта функция возвращает разницу в годах между двумя датами (в виде строк в формате 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
ответ дан 24 November 2019 в 01:07
поделиться

Что ж, вопрос кажется довольно простым. Вам нужно проверить количество «полных» лет, и только если оно равно 18, вам нужно возиться с месяцами и днями. Граничный случай: endDate.year - startDate.year == 18 , и он делится на два случая: startDate.month! = EndDate.month и startDate.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

Это все еще больше, чем однострочное лямбда, но оно все еще довольно короткое и кажется быстрым в исполнении.

-3
ответ дан 24 November 2019 в 01:07
поделиться

Я предлагаю Pyfdate

Что такое pyfdate?

Учитывая, что цель Python - быть мощным и простым в использовании -использовать скрипты язык, его особенности для работы с датами и временем не как удобные для пользователя, какими они должны быть. В цель pyfdate - исправить это ситуации, предоставляя функции для работа с датой и временем, которые такой же мощный и простой в использовании, как остальная часть Python.

учебник

0
ответ дан 24 November 2019 в 01:07
поделиться
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
1
ответ дан 24 November 2019 в 01:07
поделиться

Получите количество дней, затем разделите на 365,2425 (средний год по григорианскому календарю) за годы. Разделите месяцы на 30,436875 (среднее значение месяца по григорианскому календарю).

3
ответ дан 24 November 2019 в 01:07
поделиться

Еще одна сторонняя библиотека, не упомянутая здесь, - это mxDateTime (предшественник как python datetime , так и сторонней библиотеки ) timeutil ) может быть использован для этой задачи.

Вышеупомянутые лет назад будут:

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 в DateTime , вы можете использовать это для точности в 1 секунду):

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 (предложенного Риком Коуплендом).

1
ответ дан 24 November 2019 в 01:07
поделиться

В конце концов, у вас проблема с математикой. Если каждые 4 года у нас будет дополнительный день, а затем понизить timedelta в днях, не на 365, а на 365 * 4 + 1, то получится 4 года. Затем снова разделите его на 4. timedelta / ((365 * 4) +1) / 4 = timedelta * 4 / (365 * 4 +1)

1
ответ дан 24 November 2019 в 01:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: