如何在python中向datetime.date对象添加"3个月"?

Nat*_*han 25 python sql postgresql

Python日期计算,你在哪里?

我有一个python应用程序,需要每隔三个月绘制几年的日期.重要的是,日期每年恰好发生4次,并且日期尽可能在每年的同一天发生,并且日期尽可能在每月的同一天发生,并且日期为尽可能接近"3个月"(这是一个移动的目标,特别是在闰年).不幸的是,datetime.timedelta不支持几个月!

在python中有没有"标准"的方法来进行这个计算?

SQL方式?

如果最糟糕的情况发生,我会试着让我的应用程序询问PostgreSQL,它确实有很好的内置支持日期计算,答案如下:

# select ('2010-11-29'::date + interval '3 months')::date;
    date    
------------
 2011-02-28
(1 row)
Run Code Online (Sandbox Code Playgroud)

jat*_*ism 56

如果您正在寻找准确或"更精确"的日期,那么最好还是查看dateutil.

快速举例:

>>> from dateutil.relativedelta import relativedelta
>>> import datetime
>>> TODAY = datetime.date.today()
>>> TODAY
datetime.date(2012, 3, 6)
Run Code Online (Sandbox Code Playgroud)

现在添加3个月TODAY,观察它完全匹配当天(请注意relativedelta(months=3)relativedelta(month=3)具有不同的行为.确保使用months这些示例!).

>>> three_mon_rel = relativedelta(months=3)
>>> TODAY + three_mon_rel
datetime.date(2012, 6, 6)
Run Code Online (Sandbox Code Playgroud)

并且它在整个一年中保持一致.字面上每三个月,当天(必须继续添加因为某种原因乘以a 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)
Run Code Online (Sandbox Code Playgroud)

虽然mVChr建议的解决方案虽然绝对"足够好",但随着时间的推移会略微漂移:

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

在一年的过程中,月份的日子一直在滑动:

>>> 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)
Run Code Online (Sandbox Code Playgroud)

  • `relativedelta(months = 3)`和`relativedelta(month = 3)`有不同的行为,我有点挣扎,看到我错过了'月'的's',也许这很好被提及在你非常好的答案:) (6认同)

mVC*_*Chr 7

import datetime

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

然后将每个新年"标准化"到原始日期(除非2月29日)

  • 此外,这里三个月只是91天,除非你做'3*365.0/12`.然后是91天6小时. (3认同)