我想在指定日期添加一个月
import datetime
dt = datetime.datetime(year=2014, month=5, day=2)
所以我应该
datetime.datetime(year=2014, month=6, day=2)
但是
dt = datetime.datetime(year=2015, month=1, day=31)
我应该
datetime.datetime(year=2015, month=3, day=1)
因为没有2015-02-31(我希望我的结果在之后一天完成)
有些月份有31天,有些月份有30天,有些是29天,有些是28天!
所以添加datetime.timedelta
可能不是一种好的做法(因为我们不知道要添加的天数)
我注意到Pandas有一个有趣的概念DateOffset
http://pandas.pydata.org/pandas-docs/stable/timeseries.html#dateoffset-objects
但我找不到Month
偏移量,只有MonthBegin
或MonthEnd
我也看到了这篇文章 How do I calculate the date six months from the current date using the datetime Python module?
所以我尝试了dateutil.relativedelta
但是
from dateutil.relativedelta import relativedelta
datetime.datetime(year=2015, month=1, day=31)+relativedelta(months=1)
返回
datetime.datetime(2015, 2, 28, 0, 0)
所以结果在前一天四舍五入。
之后是否有(干净的)方式来回合?
编辑:
我举了一个月的例子来添加,但我也希望能够添加例如:2年零6个月(使用relativedelta(years=2, months=6)
)
答案 0 :(得分:4)
您可以使用dateutil.relativedelta.relativedelta
并手动检查datetime.day
属性,如果原始日期大于新的一天,则添加一天。
下面的函数接受datetime
对象和relativedelta
对象。请注意,下面的代码只能使用数年和数月,如果你使用低于(天,小时等)的任何东西,我认为它不会起作用。您可以轻松修改此函数以将years
和months
作为参数,然后在函数本身内构造relativedelta
。
from datetime import datetime
from dateutil.relativedelta import relativedelta
def add_time(d, rd):
day = relativedelta(days=+1)
out = d + rd
if d.day > out.day:
out = out + day
return out
# Check that it "rolls over"
print(add_time(datetime(year=2015, month=1, day=29), relativedelta(years=+4, months=+1))) # 2019-03-01 00:00:00
print(add_time(datetime(year=2015, month=3, day=31), relativedelta(years=+0, months=+2))) # 2015-05-01 00:00:00
# Check that it handles "normal" scenarios
print(add_time(datetime(year=2015, month=6, day=19), relativedelta(months=+1))) # 2015-07-19 00:00:00
print(add_time(datetime(year=2015, month=6, day=30), relativedelta(years=+2, months=+1))) # 2017-07-30 00:00:00
# Check across years
print(add_time(datetime(year=2015, month=12, day=25), relativedelta(months=+1))) # 2016-01-25 00:00:00
# Check leap years
print(add_time(datetime(year=2016, month=1, day=29), relativedelta(years=+4, months=+1))) # 2020-02-29 00:00:00
答案 1 :(得分:2)
这似乎有效。它很干净,但不漂亮:
def add_month(now):
try:
then = (now + relativedelta(months=1)).replace(day=now.day)
except ValueError:
then = (now + relativedelta(months=2)).replace(day=1)
return then
for now in [datetime(2015, 1, 20), datetime(2015, 1, 31), datetime(2015, 2, 28)]:
print now, add_month(now)
打印:
2015-01-20 00:00:00 2015-02-20 00:00:00
2015-01-31 00:00:00 2015-03-01 00:00:00
2015-02-28 00:00:00 2015-03-28 00:00:00
它会增加一个月并尝试将当天替换为原始日期。如果成功,则不是特例。如果失败(ValueError),我们必须再添加一个月并转到第一天。
答案 2 :(得分:0)
快速解决方案:
import datetime
import calendar
dt = datetime.datetime(year=2014, month=5, day=2)
d = calendar.monthrange(dt.year,dt.month+1)[1]
print dt+datetime.timedelta(days=d+1)
第一个输入(year=2014, month=5, day=2)
的输出:
2014-06-02 00:00:00
第二个输入(year=2015, month=1, day=31)
的输出:
2015-03-01 00:00:00
答案 3 :(得分:0)
使用下面的方法:
def datetime_offset_by_months(datetime_origin, n=1):
"""
datetime offset by months
:param datetime_origin: the original datetime
:param n: count of months
:return: after offset datetime
"""
# create a shortcut object for one day
one_day = datetime.timedelta(days=1)
# first use div and mod to determine year cycle
q, r = divmod(datetime_origin.month + n, 12)
# create a datetime_offset
# to be the last day of the target month
datetime_offset = datetime.datetime(
datetime_origin.year + q, r + 1, 1) - one_day
'''
if input date is the last day of this month
then the output date should also be the last
day of the target month, although the day
www.iplaypy.com
may be different.
for example:
datetime_origin = 8.31
datetime_offset = 9.30
'''
if datetime_origin.month != (datetime_origin + one_day).month:
return datetime_offset
'''
if datetime_origin day is bigger than last day of
target month, then, use datetime_offset
for example:
datetime_origin = 10.31
datetime_offset = 11.30
'''
if datetime_origin.day >= datetime_offset.day:
return datetime_offset
'''
then, here, we just replace datetime_offset's day
with the same of datetime_origin, that's ok.
'''
return datetime_offset.replace(day= datetime_origin.day)
使用它:
import datetime
now_date = datetime.datetime.now()
off_set_datetime = datetime_offset_by_months(now_date, -2)
print(off_set_datetime)