I am using the datetime Python module. I am looking to calculate the date 6 months from the current date. Could someone give me a little help doing this?
我使用的是datetime Python模块。我想从当前日期算起6个月的日期。有人能给我一点帮助吗?
The reason I want to generate a date 6 months from the current date is to produce a Review Date. If the user enters data into the system it will have a review date of 6 months from the date they entered the data.
我想从当前日期起6个月的日期是为了产生一个审查日期。如果用户将数据输入到系统中,它将从输入数据的日期起计算6个月。
37 个解决方案
#1
34
import datetime
print (datetime.date.today() + datetime.timedelta(6*365/12)).isoformat()
#2
661
I found this solution to be good. (This uses the python-dateutil extension)
我发现这个方法很好。(这使用了python-dateutil扩展)
from datetime import date
from dateutil.relativedelta import relativedelta
six_months = date.today() + relativedelta(months=+6)
The advantage of this approach is that it takes care of issues with 28, 30, 31 days etc. This becomes very useful in handling business rules and scenarios (say invoice generation etc.)
焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点
$ date(2010,12,31)+relativedelta(months=+1)
datetime.date(2011, 1, 31)
$ date(2010,12,31)+relativedelta(months=+2)
datetime.date(2011, 2, 28)
#3
40
Well, that depends what you mean by 6 months from the current date.
好吧,这取决于你说的6个月后的当前日期。
-
Using natural months:
使用自然月:
(day, month, year) = (day, (month+6)%12, year+(month+6)/12)
-
Using a banker's definition, 6*30:
使用银行家的定义,6*30:
date += datetime.timedelta(6*30)
#4
16
For beginning of month to month calculation:
月初至月计算:
from datetime import timedelta
from dateutil.relativedelta import relativedelta
end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)
#5
12
What do you mean by '6 months'. Is 2009-02-13 + 6 months == 2009-08-13 or is it 2009-02-13 + 6*30 days?
你说的“6个月”是什么意思?2009-02-13 + 6个月== 2009-08-13还是2009-02-13 + 6*30天?
import mx.DateTime as dt
#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'
#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'
More info about mx.DateTime
更多信息关于mx.DateTime
#6
11
This solution works correctly for December, which most of the answers on this page do not. You need to first shift the months from base 1 (ie Jan = 1) to base 0 (ie Jan = 0) before using modulus ( % ) or integer division ( // ), otherwise November (11) plus 1 month gives you 12, which when finding the remainder ( 12 % 12 ) gives 0.
这个解决方案适用于12月份,而这个页面的大多数答案都没有。首先需要将从基地1个月(即1月= 1)基地0(即1月= 0)使用前模量(%)或整数的除法(/ /),否则11月(11)+ 1个月给你12日,当发现其余(12 12%)为0。
(And dont suggest "(month % 12) + 1" or Oct + 1 = december!)
(并且不要建议“(月% 12)+ 1”或10月+ 1 = 12月!)
def AddMonths(d,x):
newmonth = ((( d.month - 1) + x ) % 12 ) + 1
newyear = d.year + ((( d.month - 1) + x ) / 12 )
return datetime.date( newyear, newmonth, d.day)
However ... This doesnt account for problem like Jan 31 + one month. So we go back to the OP - what do you mean by adding a month? One soln is to backtrack until you get to a valid day, given that most people would presume the last day of jan, plus one month, equals the last day of Feb. This will work on negative numbers of months too. Proof:
然而……这并不能解释1月31 + 1个月的问题。所以我们回到OP -你说增加一个月是什么意思?一个soln将会回溯到一个有效的日期,因为大多数人会假定1月的最后一天,加上一个月,等于2月的最后一天,这也会影响到月的负数。证明:
>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>>
#7
10
There's no direct way to do it with Python's datetime.
使用Python的datetime并没有直接的方法。
Check out the relativedelta type at python-dateutil. It allows you to specify a time delta in months.
查看python-dateutil的相对delta类型。它允许您在几个月内指定一个时间增量。
#8
9
I know this was for 6 months, however the answer shows in google for "adding months in python" if you are adding one month:
我知道这是6个月的时间,但是如果你加一个月的话,谷歌的答案会显示“在python里增加几个月”。
import calendar
date = datetime.date.today() //Or your date
datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])
this would count the days in the current month and add them to the current date, using 365/12 would ad 1/12 of a year can causes issues for short / long months if your iterating over the date.
这将计算当前月份的天数,并将它们添加到当前日期,使用365/12将会在一年的1/12的时间内,如果您的迭代周期超过了日期,则会导致短/长月份的问题。
#9
8
Dateutil package has implementation of such functionality. But be aware, that this will be naive, as others pointed already.
Dateutil包实现了这种功能。但请注意,这将是天真的,正如其他人所指出的那样。
#10
8
So, here is an example of the dateutil.relativedelta
which I found useful for iterating through the past year, skipping a month each time to the present date:
这是dateutil的一个例子。在过去的一年里,我发现相对的delta是有用的,每个月可以跳过一个月。
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
... day = today - relativedelta(months=month_count)
... print day
... month_count += 1
...
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968
As with the other answers, you have to figure out what you actually mean by "6 months from now." If you mean "today's day of the month in the month six years in the future" then this would do:
和其他答案一样,你必须弄清楚“6个月后”你的实际意思是什么。如果你的意思是“在未来的6年里这个月的今天”,那么这将是:
datetime.datetime.now() + relativedelta(months=6)
#11
6
Just use the timetuple method to extract the months, add your months and build a new dateobject. If there is a already existing method for this I do not know it.
只需使用timetuple方法提取月份,添加您的月份并构建一个新的dateobject。如果有一个已经存在的方法,我不知道它。
import datetime
def in_the_future(months=1):
year, month, day = datetime.date.today().timetuple()[:3]
new_month = month + months
return datetime.date(year + (new_month / 12), new_month % 12, day)
The API is a bit clumsy, but works as an example. Will also obviously not work on corner-cases like 2008-01-31 + 1 month. :)
这个API有点笨拙,但是作为一个例子。显然也不会在类似于2008-01-31 + 1个月这样的转角上工作。:)
#12
3
I have a better way to solve the 'February 31st' problem:
我有一个更好的办法来解决2月31日的问题:
def add_months(start_date, months):
import calendar
year = start_date.year + (months / 12)
month = start_date.month + (months % 12)
day = start_date.day
if month > 12:
month = month % 12
year = year + 1
days_next = calendar.monthrange(year, month)[1]
if day > days_next:
day = days_next
return start_date.replace(year, month, day)
I think that it also works with negative numbers (to subtract months), but I haven't tested this very much.
我认为它也适用于负数(减去月),但我还没有做过很多测试。
#13
2
The QDate class of PyQt4 has an addmonths function.
PyQt4的QDate类具有一个addmonth函数。
>>>from PyQt4.QtCore import QDate
>>>dt = QDate(2009,12,31)
>>>required = dt.addMonths(6)
>>>required
PyQt4.QtCore.QDate(2010, 6, 30)
>>>required.toPyDate()
datetime.date(2010, 6, 30)
#14
2
Modified the AddMonths() for use in Zope and handling invalid day numbers:
修改了在Zope中使用的AddMonths()并处理无效的日期:
def AddMonths(d,x):
days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
newyear = d.year() + ((( d.month() - 1) + x ) // 12 )
if d.day() > days_of_month[newmonth-1]:
newday = days_of_month[newmonth-1]
else:
newday = d.day()
return DateTime( newyear, newmonth, newday)
#15
2
import time
def add_month(start_time, months):
ret = time.strptime(start_time, '%Y-%m-%d')
t = list(ret)
t[1] += months
if t[1] > 12:
t[0] += 1 + int(months / 12)
t[1] %= 12
return int(time.mktime(tuple(t)))
#16
2
How about this? Not using another library (dateutil
) or timedelta
? building on vartec's answer I did this and I believe it works:
这个怎么样?不使用另一个库(dateutil)或timedelta?在vartec的回答上我做了这个,我相信它是可行的:
import datetime
today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)
I tried using timedelta
, but because it is counting the days, 365/2
or 6*356/12
does not always translate to 6 months, but rather 182 days. e.g.
我试着使用timedelta,但是因为它计算的是天数,365/2或6*356/12并不总是转化为6个月,而是182天。如。
day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10
print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08
I believe that we usually assume that 6 month's from a certain day will land on the same day of the month but 6 months later (i.e. 2015-03-10
--> 2015-09-10
, Not 2015-09-08
)
我认为我们通常假设6个月的某一天会在一个月的同一天登陆,但6个月后(即2015-03-10 -> 2015-09-10,而不是2015-09-08)
I hope you find this helpful.
我希望你觉得这有帮助。
#17
1
I solved this problem like this:
我解决了这个问题:
import calendar
from datetime import datetime
moths2add = 6
now = datetime.now()
current_year = now.year
current_month = now.month
#count days in months you want to add using calendar module
days = sum(
[calendar.monthrange(current_year, elem)[1] for elem in range(current_month, current_month + moths)]
)
print now + days
#18
1
Modified Johannes Wei's answer in the case 1new_month = 121. This works perfectly for me. The months could be positive or negative.
修正了约翰内斯·魏的答案,在这个案例中,1new_month = 121。这对我来说是完美的。月份可能是正的,也可能是负的。
def addMonth(d,months=1):
year, month, day = d.timetuple()[:3]
new_month = month + months
return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)
#19
1
Yet another solution - hope someone will like it:
另一个解决方案——希望有人会喜欢它:
def add_months(d, months):
return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)
This solution doesn't work for days 29,30,31 for all cases, so more robust solution is needed (which is not so nice anymore :) ):
这个解决方案在第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")
#20
1
From this answer, see parsedatetime. Code example follows. More details: unit test with many natural-language -> YYYY-MM-DD conversion examples, and apparent parsedatetime conversion challenges/bugs.
从这个答案中,可以看到parsedatetime。代码示例。更多细节:使用许多自然语言的单元测试——> YYYY-MM-DD转换示例,以及明显的parsedatetime转换挑战/bug。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date
# from https://github.com/bear/parsedatetime
import parsedatetime as pdt
def print_todays_date():
todays_day_of_week = calendar.day_name[date.today().weekday()]
print "today's date = " + todays_day_of_week + ', ' + \
time.strftime('%Y-%m-%d')
def convert_date(natural_language_date):
cal = pdt.Calendar()
(struct_time_date, success) = cal.parse(natural_language_date)
if success:
formal_date = time.strftime('%Y-%m-%d', struct_time_date)
else:
formal_date = '(conversion failed)'
print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)
print_todays_date()
convert_date('6 months')
The above code generates the following from a MacOSX machine:
上面的代码从MacOSX机器生成如下:
$ ./parsedatetime_simple.py
today's date = Wednesday, 2015-05-13
6 months -> 2015-11-13
$
#21
1
given that your datetime variable is called date:
假定您的datetime变量名为date:
date=datetime.datetime(year=date.year+int((date.month+6)/12),
month=(date.month+6)%13 + (1 if (date.month +
months>12) else 0), day=date.day)
#22
1
General function to get next date after/before x months.
一般功能在x个月后的下一个日期。
from datetime import date def after_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 = after_month(today, mm) print(next_date)
#23
0
Use the python datetime module to add a timedelta of six months to datetime.today() .
使用python datetime模块为datetime添加一个6个月的时间增量。
http://docs.python.org/library/datetime.html
http://docs.python.org/library/datetime.html
You will of course have to solve the issue raised by Johannes Weiß-- what do you mean by 6 months?
你当然要解决提出的问题Johannes Weiß——6个月是什么意思?
#24
0
This is what I came up with. It moves the correct number of months and years but ignores days (which was what I needed in my situation).
这就是我想到的。它移动了正确的月份和年份,但忽略了天数(这正是我所需要的)。
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)
#25
0
I use this function to change year and month but keep day:
我用这个函数来改变年和月,但保留一天:
def replace_month_year(date1, year2, month2):
try:
date2 = date1.replace(month = month2, year = year2)
except:
date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
return date2
You should write:
你应该写:
new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)
#26
0
I think it would be safer to do something like this instead of manually adding days:
我认为这样做会更安全,而不是手工添加天数:
import datetime
today = datetime.date.today()
def addMonths(dt, months = 0):
new_month = months + dt.month
year_inc = 0
if new_month>12:
year_inc +=1
new_month -=12
return dt.replace(month = new_month, year = dt.year+year_inc)
newdate = addMonths(today, 6)
#27
0
import datetime
'''
Created on 2011-03-09
@author: tonydiep
'''
def add_business_months(start_date, months_to_add):
"""
Add months in the way business people think of months.
Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
Method: Add the number of months, roll back the date until it becomes a valid date
"""
# determine year
years_change = months_to_add / 12
# determine if there is carryover from adding months
if (start_date.month + (months_to_add % 12) > 12 ):
years_change = years_change + 1
new_year = start_date.year + years_change
# determine month
work = months_to_add % 12
if 0 == work:
new_month = start_date.month
else:
new_month = (start_date.month + (work % 12)) % 12
if 0 == new_month:
new_month = 12
# determine day of the month
new_day = start_date.day
if(new_day in [31, 30, 29, 28]):
#user means end of the month
new_day = 31
new_date = None
while (None == new_date and 27 < new_day):
try:
new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
except:
new_day = new_day - 1 #wind down until we get to a valid date
return new_date
if __name__ == '__main__':
#tests
dates = [datetime.date(2011, 1, 31),
datetime.date(2011, 2, 28),
datetime.date(2011, 3, 28),
datetime.date(2011, 4, 28),
datetime.date(2011, 5, 28),
datetime.date(2011, 6, 28),
datetime.date(2011, 7, 28),
datetime.date(2011, 8, 28),
datetime.date(2011, 9, 28),
datetime.date(2011, 10, 28),
datetime.date(2011, 11, 28),
datetime.date(2011, 12, 28),
]
months = range(1, 24)
for start_date in dates:
for m in months:
end_date = add_business_months(start_date, m)
print("%s\t%s\t%s" %(start_date, end_date, m))
#28
0
Rework of an earlier answer by user417751. Maybe not so pythonic way, but it takes care of different month lengths and leap years. In this case 31 January 2012 + 1 month = 29 February 2012.
user417751的早期回复。也许不是这样,但它需要不同的月长度和闰年。在此情况下,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)
#29
0
Here's a example which allows the user to decide how to return a date where the day is greater than the number of days in the month.
这里有一个例子,它允许用户决定如何返回一天比一个月的天数要大的日期。
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)
#30
0
Another solution: calculate sum of days in month for next n month and add result to current date.
另一个解决方案是:计算下一个月的天数,并将结果添加到当前日期。
import calendar
import datetime
def date_from_now(months):
today = datetime.datetime.today()
month = today.month
year = today.year
sum_days = 0
for i in range(int(months)):
month += 1
if month == 13:
month = 1
year += 1
sum_days += calendar.monthrange(year, month)[1]
return datetime.date.today() + datetime.timedelta(sum_days)
print(date_from_now(12)) # if to day is 2017-01-01, output: 2019-01-01
#1
34
import datetime
print (datetime.date.today() + datetime.timedelta(6*365/12)).isoformat()
#2
661
I found this solution to be good. (This uses the python-dateutil extension)
我发现这个方法很好。(这使用了python-dateutil扩展)
from datetime import date
from dateutil.relativedelta import relativedelta
six_months = date.today() + relativedelta(months=+6)
The advantage of this approach is that it takes care of issues with 28, 30, 31 days etc. This becomes very useful in handling business rules and scenarios (say invoice generation etc.)
焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点焦点
$ date(2010,12,31)+relativedelta(months=+1)
datetime.date(2011, 1, 31)
$ date(2010,12,31)+relativedelta(months=+2)
datetime.date(2011, 2, 28)
#3
40
Well, that depends what you mean by 6 months from the current date.
好吧,这取决于你说的6个月后的当前日期。
-
Using natural months:
使用自然月:
(day, month, year) = (day, (month+6)%12, year+(month+6)/12)
-
Using a banker's definition, 6*30:
使用银行家的定义,6*30:
date += datetime.timedelta(6*30)
#4
16
For beginning of month to month calculation:
月初至月计算:
from datetime import timedelta
from dateutil.relativedelta import relativedelta
end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)
#5
12
What do you mean by '6 months'. Is 2009-02-13 + 6 months == 2009-08-13 or is it 2009-02-13 + 6*30 days?
你说的“6个月”是什么意思?2009-02-13 + 6个月== 2009-08-13还是2009-02-13 + 6*30天?
import mx.DateTime as dt
#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'
#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'
More info about mx.DateTime
更多信息关于mx.DateTime
#6
11
This solution works correctly for December, which most of the answers on this page do not. You need to first shift the months from base 1 (ie Jan = 1) to base 0 (ie Jan = 0) before using modulus ( % ) or integer division ( // ), otherwise November (11) plus 1 month gives you 12, which when finding the remainder ( 12 % 12 ) gives 0.
这个解决方案适用于12月份,而这个页面的大多数答案都没有。首先需要将从基地1个月(即1月= 1)基地0(即1月= 0)使用前模量(%)或整数的除法(/ /),否则11月(11)+ 1个月给你12日,当发现其余(12 12%)为0。
(And dont suggest "(month % 12) + 1" or Oct + 1 = december!)
(并且不要建议“(月% 12)+ 1”或10月+ 1 = 12月!)
def AddMonths(d,x):
newmonth = ((( d.month - 1) + x ) % 12 ) + 1
newyear = d.year + ((( d.month - 1) + x ) / 12 )
return datetime.date( newyear, newmonth, d.day)
However ... This doesnt account for problem like Jan 31 + one month. So we go back to the OP - what do you mean by adding a month? One soln is to backtrack until you get to a valid day, given that most people would presume the last day of jan, plus one month, equals the last day of Feb. This will work on negative numbers of months too. Proof:
然而……这并不能解释1月31 + 1个月的问题。所以我们回到OP -你说增加一个月是什么意思?一个soln将会回溯到一个有效的日期,因为大多数人会假定1月的最后一天,加上一个月,等于2月的最后一天,这也会影响到月的负数。证明:
>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>>
#7
10
There's no direct way to do it with Python's datetime.
使用Python的datetime并没有直接的方法。
Check out the relativedelta type at python-dateutil. It allows you to specify a time delta in months.
查看python-dateutil的相对delta类型。它允许您在几个月内指定一个时间增量。
#8
9
I know this was for 6 months, however the answer shows in google for "adding months in python" if you are adding one month:
我知道这是6个月的时间,但是如果你加一个月的话,谷歌的答案会显示“在python里增加几个月”。
import calendar
date = datetime.date.today() //Or your date
datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])
this would count the days in the current month and add them to the current date, using 365/12 would ad 1/12 of a year can causes issues for short / long months if your iterating over the date.
这将计算当前月份的天数,并将它们添加到当前日期,使用365/12将会在一年的1/12的时间内,如果您的迭代周期超过了日期,则会导致短/长月份的问题。
#9
8
Dateutil package has implementation of such functionality. But be aware, that this will be naive, as others pointed already.
Dateutil包实现了这种功能。但请注意,这将是天真的,正如其他人所指出的那样。
#10
8
So, here is an example of the dateutil.relativedelta
which I found useful for iterating through the past year, skipping a month each time to the present date:
这是dateutil的一个例子。在过去的一年里,我发现相对的delta是有用的,每个月可以跳过一个月。
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
... day = today - relativedelta(months=month_count)
... print day
... month_count += 1
...
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968
As with the other answers, you have to figure out what you actually mean by "6 months from now." If you mean "today's day of the month in the month six years in the future" then this would do:
和其他答案一样,你必须弄清楚“6个月后”你的实际意思是什么。如果你的意思是“在未来的6年里这个月的今天”,那么这将是:
datetime.datetime.now() + relativedelta(months=6)
#11
6
Just use the timetuple method to extract the months, add your months and build a new dateobject. If there is a already existing method for this I do not know it.
只需使用timetuple方法提取月份,添加您的月份并构建一个新的dateobject。如果有一个已经存在的方法,我不知道它。
import datetime
def in_the_future(months=1):
year, month, day = datetime.date.today().timetuple()[:3]
new_month = month + months
return datetime.date(year + (new_month / 12), new_month % 12, day)
The API is a bit clumsy, but works as an example. Will also obviously not work on corner-cases like 2008-01-31 + 1 month. :)
这个API有点笨拙,但是作为一个例子。显然也不会在类似于2008-01-31 + 1个月这样的转角上工作。:)
#12
3
I have a better way to solve the 'February 31st' problem:
我有一个更好的办法来解决2月31日的问题:
def add_months(start_date, months):
import calendar
year = start_date.year + (months / 12)
month = start_date.month + (months % 12)
day = start_date.day
if month > 12:
month = month % 12
year = year + 1
days_next = calendar.monthrange(year, month)[1]
if day > days_next:
day = days_next
return start_date.replace(year, month, day)
I think that it also works with negative numbers (to subtract months), but I haven't tested this very much.
我认为它也适用于负数(减去月),但我还没有做过很多测试。
#13
2
The QDate class of PyQt4 has an addmonths function.
PyQt4的QDate类具有一个addmonth函数。
>>>from PyQt4.QtCore import QDate
>>>dt = QDate(2009,12,31)
>>>required = dt.addMonths(6)
>>>required
PyQt4.QtCore.QDate(2010, 6, 30)
>>>required.toPyDate()
datetime.date(2010, 6, 30)
#14
2
Modified the AddMonths() for use in Zope and handling invalid day numbers:
修改了在Zope中使用的AddMonths()并处理无效的日期:
def AddMonths(d,x):
days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
newyear = d.year() + ((( d.month() - 1) + x ) // 12 )
if d.day() > days_of_month[newmonth-1]:
newday = days_of_month[newmonth-1]
else:
newday = d.day()
return DateTime( newyear, newmonth, newday)
#15
2
import time
def add_month(start_time, months):
ret = time.strptime(start_time, '%Y-%m-%d')
t = list(ret)
t[1] += months
if t[1] > 12:
t[0] += 1 + int(months / 12)
t[1] %= 12
return int(time.mktime(tuple(t)))
#16
2
How about this? Not using another library (dateutil
) or timedelta
? building on vartec's answer I did this and I believe it works:
这个怎么样?不使用另一个库(dateutil)或timedelta?在vartec的回答上我做了这个,我相信它是可行的:
import datetime
today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)
I tried using timedelta
, but because it is counting the days, 365/2
or 6*356/12
does not always translate to 6 months, but rather 182 days. e.g.
我试着使用timedelta,但是因为它计算的是天数,365/2或6*356/12并不总是转化为6个月,而是182天。如。
day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10
print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08
I believe that we usually assume that 6 month's from a certain day will land on the same day of the month but 6 months later (i.e. 2015-03-10
--> 2015-09-10
, Not 2015-09-08
)
我认为我们通常假设6个月的某一天会在一个月的同一天登陆,但6个月后(即2015-03-10 -> 2015-09-10,而不是2015-09-08)
I hope you find this helpful.
我希望你觉得这有帮助。
#17
1
I solved this problem like this:
我解决了这个问题:
import calendar
from datetime import datetime
moths2add = 6
now = datetime.now()
current_year = now.year
current_month = now.month
#count days in months you want to add using calendar module
days = sum(
[calendar.monthrange(current_year, elem)[1] for elem in range(current_month, current_month + moths)]
)
print now + days
#18
1
Modified Johannes Wei's answer in the case 1new_month = 121. This works perfectly for me. The months could be positive or negative.
修正了约翰内斯·魏的答案,在这个案例中,1new_month = 121。这对我来说是完美的。月份可能是正的,也可能是负的。
def addMonth(d,months=1):
year, month, day = d.timetuple()[:3]
new_month = month + months
return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)
#19
1
Yet another solution - hope someone will like it:
另一个解决方案——希望有人会喜欢它:
def add_months(d, months):
return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)
This solution doesn't work for days 29,30,31 for all cases, so more robust solution is needed (which is not so nice anymore :) ):
这个解决方案在第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")
#20
1
From this answer, see parsedatetime. Code example follows. More details: unit test with many natural-language -> YYYY-MM-DD conversion examples, and apparent parsedatetime conversion challenges/bugs.
从这个答案中,可以看到parsedatetime。代码示例。更多细节:使用许多自然语言的单元测试——> YYYY-MM-DD转换示例,以及明显的parsedatetime转换挑战/bug。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date
# from https://github.com/bear/parsedatetime
import parsedatetime as pdt
def print_todays_date():
todays_day_of_week = calendar.day_name[date.today().weekday()]
print "today's date = " + todays_day_of_week + ', ' + \
time.strftime('%Y-%m-%d')
def convert_date(natural_language_date):
cal = pdt.Calendar()
(struct_time_date, success) = cal.parse(natural_language_date)
if success:
formal_date = time.strftime('%Y-%m-%d', struct_time_date)
else:
formal_date = '(conversion failed)'
print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)
print_todays_date()
convert_date('6 months')
The above code generates the following from a MacOSX machine:
上面的代码从MacOSX机器生成如下:
$ ./parsedatetime_simple.py
today's date = Wednesday, 2015-05-13
6 months -> 2015-11-13
$
#21
1
given that your datetime variable is called date:
假定您的datetime变量名为date:
date=datetime.datetime(year=date.year+int((date.month+6)/12),
month=(date.month+6)%13 + (1 if (date.month +
months>12) else 0), day=date.day)
#22
1
General function to get next date after/before x months.
一般功能在x个月后的下一个日期。
from datetime import date def after_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 = after_month(today, mm) print(next_date)
#23
0
Use the python datetime module to add a timedelta of six months to datetime.today() .
使用python datetime模块为datetime添加一个6个月的时间增量。
http://docs.python.org/library/datetime.html
http://docs.python.org/library/datetime.html
You will of course have to solve the issue raised by Johannes Weiß-- what do you mean by 6 months?
你当然要解决提出的问题Johannes Weiß——6个月是什么意思?
#24
0
This is what I came up with. It moves the correct number of months and years but ignores days (which was what I needed in my situation).
这就是我想到的。它移动了正确的月份和年份,但忽略了天数(这正是我所需要的)。
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)
#25
0
I use this function to change year and month but keep day:
我用这个函数来改变年和月,但保留一天:
def replace_month_year(date1, year2, month2):
try:
date2 = date1.replace(month = month2, year = year2)
except:
date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
return date2
You should write:
你应该写:
new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)
#26
0
I think it would be safer to do something like this instead of manually adding days:
我认为这样做会更安全,而不是手工添加天数:
import datetime
today = datetime.date.today()
def addMonths(dt, months = 0):
new_month = months + dt.month
year_inc = 0
if new_month>12:
year_inc +=1
new_month -=12
return dt.replace(month = new_month, year = dt.year+year_inc)
newdate = addMonths(today, 6)
#27
0
import datetime
'''
Created on 2011-03-09
@author: tonydiep
'''
def add_business_months(start_date, months_to_add):
"""
Add months in the way business people think of months.
Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
Method: Add the number of months, roll back the date until it becomes a valid date
"""
# determine year
years_change = months_to_add / 12
# determine if there is carryover from adding months
if (start_date.month + (months_to_add % 12) > 12 ):
years_change = years_change + 1
new_year = start_date.year + years_change
# determine month
work = months_to_add % 12
if 0 == work:
new_month = start_date.month
else:
new_month = (start_date.month + (work % 12)) % 12
if 0 == new_month:
new_month = 12
# determine day of the month
new_day = start_date.day
if(new_day in [31, 30, 29, 28]):
#user means end of the month
new_day = 31
new_date = None
while (None == new_date and 27 < new_day):
try:
new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
except:
new_day = new_day - 1 #wind down until we get to a valid date
return new_date
if __name__ == '__main__':
#tests
dates = [datetime.date(2011, 1, 31),
datetime.date(2011, 2, 28),
datetime.date(2011, 3, 28),
datetime.date(2011, 4, 28),
datetime.date(2011, 5, 28),
datetime.date(2011, 6, 28),
datetime.date(2011, 7, 28),
datetime.date(2011, 8, 28),
datetime.date(2011, 9, 28),
datetime.date(2011, 10, 28),
datetime.date(2011, 11, 28),
datetime.date(2011, 12, 28),
]
months = range(1, 24)
for start_date in dates:
for m in months:
end_date = add_business_months(start_date, m)
print("%s\t%s\t%s" %(start_date, end_date, m))
#28
0
Rework of an earlier answer by user417751. Maybe not so pythonic way, but it takes care of different month lengths and leap years. In this case 31 January 2012 + 1 month = 29 February 2012.
user417751的早期回复。也许不是这样,但它需要不同的月长度和闰年。在此情况下,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)
#29
0
Here's a example which allows the user to decide how to return a date where the day is greater than the number of days in the month.
这里有一个例子,它允许用户决定如何返回一天比一个月的天数要大的日期。
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)
#30
0
Another solution: calculate sum of days in month for next n month and add result to current date.
另一个解决方案是:计算下一个月的天数,并将结果添加到当前日期。
import calendar
import datetime
def date_from_now(months):
today = datetime.datetime.today()
month = today.month
year = today.year
sum_days = 0
for i in range(int(months)):
month += 1
if month == 13:
month = 1
year += 1
sum_days += calendar.monthrange(year, month)[1]
return datetime.date.today() + datetime.timedelta(sum_days)
print(date_from_now(12)) # if to day is 2017-01-01, output: 2019-01-01