我正在使用datetime Python模块。我希望从当前日期计算6个月的日期。有人能帮我一下吗?
我想从当前日期生成一个6个月后的日期的原因是为了生成一个回顾日期。如果用户在系统中输入数据,系统将有从输入数据之日起6个月的审查日期。
我正在使用datetime Python模块。我希望从当前日期计算6个月的日期。有人能帮我一下吗?
我想从当前日期生成一个6个月后的日期的原因是为了生成一个回顾日期。如果用户在系统中输入数据,系统将有从输入数据之日起6个月的审查日期。
当前回答
下面是一个示例,它允许用户决定如何返回一个日期,其中一天大于一个月中的天数。
def add_months(date, months, endOfMonthBehaviour='RoundUp'):
assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
'Unknown end of month behaviour'
year = date.year + (date.month + months - 1) / 12
month = (date.month + months - 1) % 12 + 1
day = date.day
last = monthrange(year, month)[1]
if day > last:
if endOfMonthBehaviour == 'RoundDown' or \
endOfMonthBehaviour == 'RoundOut' and months < 0 or \
endOfMonthBehaviour == 'RoundIn' and months > 0:
day = last
elif endOfMonthBehaviour == 'RoundUp' or \
endOfMonthBehaviour == 'RoundOut' and months > 0 or \
endOfMonthBehaviour == 'RoundIn' and months < 0:
# we don't need to worry about incrementing the year
# because there will never be a day in December > 31
month += 1
day = 1
return datetime.date(year, month, day)
>>> from calendar import monthrange
>>> import datetime
>>> add_months(datetime.datetime(2016, 1, 31), 1)
datetime.date(2016, 3, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2)
datetime.date(2015, 12, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
datetime.date(2015, 11, 30)
其他回答
按月开始计算:
from datetime import timedelta
from dateutil.relativedelta import relativedelta
end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)
还有另一个解决方案,希望有人会喜欢:
def add_months(d, months):
return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)
这个解决方案并不适用于所有情况下的第29、30、31天,所以需要更健壮的解决方案(这已经不是那么好了:)):
def add_months(d, months):
for i in range(4):
day = d.day - i
try:
return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
except:
pass
raise Exception("should not happen")
我找不到这个问题的确切解决方案,所以我将发布我的解决方案,以防使用标准日历和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)
使用下面给出的函数,你可以得到x个月之后/之前的日期。
from datetime import date def next_month(given_date, month): yyyy = int(((given_date.year * 12 + given_date.month) + month)/12) mm = int(((given_date.year * 12 + given_date.month) + month)%12) if mm == 0: yyyy -= 1 mm = 12 return given_date.replace(year=yyyy, month=mm) if __name__ == "__main__": today = date.today() print(today) for mm in [-12, -1, 0, 1, 2, 12, 20 ]: next_date = next_month(today, mm) print(next_date)
def addDay(date, number):
for i in range(number)
#try to add a day
try:
date = date.replace(day = date.day + 1)
#in case it's impossible ex:january 32nd add a month and restart at day 1
except:
#add month part
try:
date = date.replace(month = date.month +1, day = 1)
except:
date = date.replace(year = date.year +1, month = 1, day = 1)
写给还在读这篇文章的人。我认为这段代码更加清晰,特别是与使用模(%)的代码相比。
很抱歉有语法错误,英语不是我的主要语言