I have a python app that needs to plot out dates every three months for several years. It's important that the dates occur exactly 4 times a year, and that the dates occur on the same day each year as much as possible, and that the dates occur on the same day of the month as much as possible, and that the dates be as close to "3 months" apart as they can be (which is a moving target, especially on leap year). Unfortunately,
datetime.timedelta doesn't support months!
Is there a "standard" way to do this calculation in python???
If worst comes to worst, I will punt and have my app ask PostgreSQL, who does have nice built-in support for date calculations, for the answer like this:
# select ('2010-11-29'::date + interval '3 months')::date; date ------------ 2011-02-28 (1 row)
If you're looking for exact or "more precise" dates, you're probably better off checking out dateutil.
>>> from dateutil.relativedelta import relativedelta >>> import datetime >>> TODAY = datetime.date.today() >>> TODAY datetime.date(2012, 3, 6)
Now add 3 months to
TODAY, observe that it matches the day exactly (Note that
relativedelta(month=3) have different behaviors. Make sure to use
months for these examples!).
>>> three_mon_rel = relativedelta(months=3) >>> TODAY + three_mon_rel datetime.date(2012, 6, 6)
And it stays consistent throughout the course of a year. Literally every three months, on the day (had to keep adding because for some reason multiplying a
relativedelta and adding it to a
datetime.date object throws a
>>> 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)
Whereas the mVChr's suggested solution, while definitely "good enough", drifts slightly over time:
>>> three_mon_timedelta = datetime.timedelta(days=3 * 365/12) >>> TODAY + three_mon_timedelta datetime.date(2012, 6, 5)
And over the course of a year, the day of month keeps sliding:
>>> 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)
import datetime some_date = datetime.date.today() three_months = datetime.timedelta(3*365/12) print (some_date + three_months).isoformat() # => '2012-06-01'
Then "normalize" every new year to the original date's day (unless Feb 29)