我正在使用datetime Python模块。我希望从当前日期计算6个月的日期。有人能帮我一下吗?
我想从当前日期生成一个6个月后的日期的原因是为了生成一个回顾日期。如果用户在系统中输入数据,系统将有从输入数据之日起6个月的审查日期。
我正在使用datetime Python模块。我希望从当前日期计算6个月的日期。有人能帮我一下吗?
我想从当前日期生成一个6个月后的日期的原因是为了生成一个回顾日期。如果用户在系统中输入数据,系统将有从输入数据之日起6个月的审查日期。
当前回答
user417751之前回答的重做。也许不是那么python的方式,但它照顾到不同的月份长度和闰年。在本例中,2012年1月31日+ 1个月= 2012年2月29日。
import datetime
import calendar
def add_mths(d, x):
newday = d.day
newmonth = (((d.month - 1) + x) % 12) + 1
newyear = d.year + (((d.month - 1) + x) // 12)
if newday > calendar.mdays[newmonth]:
newday = calendar.mdays[newmonth]
if newyear % 4 == 0 and newmonth == 2:
newday += 1
return datetime.date(newyear, newmonth, newday)
其他回答
按月开始计算:
from datetime import timedelta
from dateutil.relativedelta import relativedelta
end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)
这是我想到的。它移动了正确的月份和年份,但忽略了天数(这是我的情况所需要的)。
import datetime
month_dt = 4
today = datetime.date.today()
y,m = today.year, today.month
m += month_dt-1
year_dt = m//12
new_month = m%12
new_date = datetime.date(y+year_dt, new_month+1, 1)
我使用replace()方法并编写了这个递归函数。dt是一个日期时间。datetime对象:
def month_timedelta(dt, m):
y = m // 12
dm = m % 12
if y == 0:
if dt.month + m <= 12:
return dt.replace(month = dt.month + m)
else:
dy = (dt.month + m) // 12
ndt = dt.replace(year=dt.year + dy)
return ndt.replace(month=(ndt.month + m) % 12)
else:
return month_timedelta(dt.replace(year=dt.year + y),dm)
我对Tony Diep的答案的修改,可能稍微更优雅(当然,Python 2,匹配问题和原始答案的日期,对于Python 3,必要时修改,至少包括/ to //):
def add_months(date, months):
month = date.month + months - 1
year = date.year + (month / 12)
month = (month % 12) + 1
day = date.day
while (day > 0):
try:
new_date = date.replace(year=year, month=month, day=day)
break
except:
day = day - 1
return new_date
根据“业务需求”解释添加月份,即日期映射到月底之后,应该映射到月底,而不是下一个月。
我找不到这个问题的确切解决方案,所以我将发布我的解决方案,以防使用标准日历和datetime库可能有任何帮助。这适用于添加和减去月份,并考虑月末滚动和最后一个月比第一个月天数少的情况。如果你正在寻找更复杂的操作,我还有一个更通用的解决方案,它添加了定期间隔(天,月,年,季度,学期等),如:“1m”,“-9m”,“-1.5y”,“-3q”,“1s”等。
from datetime import datetime
from calendar import monthrange
def date_bump_months(start_date, months):
"""
bumps months back and forth.
--> if initial date is end-of-month, i will move to corresponding month-end
--> ir inital date.day is greater than end of month of final date, it casts it to momth-end
"""
signbit = -1 if months < 0 else 1
d_year, d_month = divmod(abs(months),12)
end_year = start_date.year + d_year*signbit
end_month = 0
if signbit ==-1:
if d_month < start_date.month:
end_month = start_date.month - d_month
else:
end_year -=1
end_month = 12 - (d_month - start_date.month)
else:
end_month +=start_date.month
if end_month > 12:
end_year +=1
end_month -=12
# check if we are running end-of-month dates
eom_run = monthrange(start_date.year, start_date.month)[1]==start_date.day
eom_month = monthrange((end_year), (end_month))[1]
if eom_run:
end_day = eom_month
else:
end_day = min(start_date.day, eom_month )
return date(end_year, end_month, end_day)