Подтвердить что ты не робот

Как добавить "3 месяца" к объекту datetime.date в python?

Расчеты даты Python, где вы?

У меня есть приложение python, которое нужно составлять даты каждые три месяца в течение нескольких лет. Важно, чтобы даты происходили ровно 4 раза в год и чтобы даты происходили в тот же день каждый год в максимально возможной степени и чтобы даты происходили в тот же день месяца, насколько это возможно, и чтобы даты были как можно ближе к "3 месяцам" (что является движущей целью, особенно в високосный год). К сожалению, datetime.timedelta не поддерживает месяцы!

Есть ли "стандартный" способ сделать это вычисление в python?

Путь SQL?

Если худшее придет к худшему, я буду плутать и попросить приложение спросить PostgreSQL, у которого есть хорошая встроенная поддержка вычислений даты, для ответа следующим образом:

# select ('2010-11-29'::date + interval '3 months')::date;
    date    
------------
 2011-02-28
(1 row)
4b9b3361

Ответ 1

Если вы ищете точные или "более точные" даты, вам, вероятно, лучше не проверять dateutil.

Быстрый пример:

>>> from dateutil.relativedelta import relativedelta
>>> import datetime
>>> TODAY = datetime.date.today()
>>> TODAY
datetime.date(2012, 3, 6)

Теперь добавьте 3 месяца в TODAY, обратите внимание, что он точно соответствует точному дню (обратите внимание, что relativedelta(months=3) и relativedelta(month=3) имеют разные типы поведения. Обязательно используйте months для этих примеров!).

>>> three_mon_rel = relativedelta(months=3)
>>> TODAY + three_mon_rel
datetime.date(2012, 6, 6)

И он остается неизменным в течение года. Буквально раз в три месяца, в день (приходилось добавлять, потому что почему-то умножая relativedelta и добавляя его к объекту datetime.date бросает a TypeError):

>>> TODAY + three_mon_rel + three_mon_rel
datetime.date(2012, 9, 6)
>>> TODAY + three_mon_rel + three_mon_rel + three_mon_rel
datetime.date(2012, 12, 6)
>>> TODAY + three_mon_rel + three_mon_rel + three_mon_rel + three_mon_rel
datetime.date(2013, 3, 6)

В то время как предлагаемое решение mVChr, хотя и определенно "достаточно хорошо", со временем слегка смещается:

>>> three_mon_timedelta = datetime.timedelta(days=3 * 365/12)
>>> TODAY + three_mon_timedelta
datetime.date(2012, 6, 5)

И в течение года день месяца продолжает скользить:

>>> TODAY + three_mon_timedelta * 2
datetime.date(2012, 9, 4)
>>> TODAY + three_mon_timedelta * 3
datetime.date(2012, 12, 4)
>>> TODAY + three_mon_timedelta * 4
datetime.date(2013, 3, 5)

Ответ 2

import datetime

some_date = datetime.date.today()
three_months = datetime.timedelta(3*365/12)
print (some_date + three_months).isoformat()
# => '2012-06-01'

Затем "нормализуйте" каждый новый год до исходного дня (кроме 29 февраля)