从Python中的date中减去一个月的最简单的方法是什么?

如果只有timedelta在它的构造函数中有一个月份参数。 那么做这个最简单的方法是什么?

编辑:我没有想太多,如下所述。 真的是我想要的是上个月的任何一天,因为最终我只会去年和月。 所以给定一个date时间对象,返回上个月的任何date时间对象最简单的方法是什么

尝试这个:

def monthdelta(date, delta): m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12 if not m: m = 12 d = min(date.day, [31, 29 if y%4==0 and not y%400==0 else 28,31,30,31,30,31,31,30,31,30,31][m-1]) return date.replace(day=d,month=m, year=y) >>> for m in range(-12, 12): print(monthdelta(datetime.now(), m)) 2009-08-06 16:12:27.823000 2009-09-06 16:12:27.855000 2009-10-06 16:12:27.870000 2009-11-06 16:12:27.870000 2009-12-06 16:12:27.870000 2010-01-06 16:12:27.870000 2010-02-06 16:12:27.870000 2010-03-06 16:12:27.886000 2010-04-06 16:12:27.886000 2010-05-06 16:12:27.886000 2010-06-06 16:12:27.886000 2010-07-06 16:12:27.886000 2010-08-06 16:12:27.901000 2010-09-06 16:12:27.901000 2010-10-06 16:12:27.901000 2010-11-06 16:12:27.901000 2010-12-06 16:12:27.901000 2011-01-06 16:12:27.917000 2011-02-06 16:12:27.917000 2011-03-06 16:12:27.917000 2011-04-06 16:12:27.917000 2011-05-06 16:12:27.917000 2011-06-06 16:12:27.933000 2011-07-06 16:12:27.933000 >>> monthdelta(datetime(2010,3,30), -1) datetime.datetime(2010, 2, 28, 0, 0) >>> monthdelta(datetime(2008,3,30), -1) datetime.datetime(2008, 2, 29, 0, 0) 

编辑更正以处理一天。

编辑另请参阅困惑的答案,它指出了一个简单的d

 d = min(date.day, calendar.monthrange(y, m)[1]) 

你可以使用第三方的dateutil模块(PyPI条目在这里 )。

 import datetime import dateutil.relativedelta d = datetime.datetime.strptime("2013-03-31", "%Y-%m-%d") d2 = d - dateutil.relativedelta.relativedelta(months=1) print d2 

输出:

 2013-02-28 00:00:00 

将原始问题编辑为“前一个月的任何date时间对象”后,可以通过从第一个月中减去1天来轻松完成。

 from datetime import datetime, timedelta def a_day_in_previous_month(dt): return datetime(dt.year, dt.month, 1) - timedelta(days=1) 

邓肯的答案 (我没有足够的评论)的一个变种,它使用calendar.monthrange大大简化了月份的最后一天的计算:

 import calendar def monthdelta(date, delta): m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12 if not m: m = 12 d = min(date.day, calendar.monthrange(y, m)[1]) return date.replace(day=d,month=m, year=y) 

在Python中获取本月最后一天的月份信息

如果只有timedelta在它的构造函数中有一个月份参数。 那么做这个最简单的方法是什么?

当你从3月30日那天减去一个月时,你想要什么结果呢? 这是增加或减less月份的问题:月份有不同的长度! 在某些应用程序中,例外是适当的,在其他情况下,“在上个月的最后一天”可以使用(但是这是真正的疯狂的算术,减去一个月,然后增加一个月不是一个整体没有操作! ,但在其他情况下,除了date之外,还要保留一些关于事实的说明,例如,“我要说的是2月28日,但是如果真的存在,我真的想要2月30日”,这样,再增加或减去一个月这可以使事情再次正确(和后者显然需要一个自定义类持有一个数据加S /事情)。

对于所有的应用程序来说,没有一个真正的解决scheme是可以容忍的,而且你还没有告诉我们你的具体应用程序的需求是否是这个可怜的操作的语义,所以我们在这里没有太多的帮助。

如果你只想要在上个月的任何一天,最简单的事情就是减去当前date的天数,这会给你上个月的最后一天。

例如,从任何date开始:

 >>> import datetime >>> today = datetime.date.today() >>> today datetime.date(2016, 5, 24) 

减去当前date的天数,我们得到:

 >>> last_day_previous_month = today - datetime.timedelta(days=today.day) >>> last_day_previous_month datetime.date(2016, 4, 30) 

这足以满足上个月任何一天的简化需求。

但是现在你已经拥有了,你也可以在这个月的任何一天,包括你开始的那一天(也就是减去一个月差不多):

 >>> same_day_last_month = last_day_previous_month.replace(day=today.day) >>> same_day_last_month datetime.date(2016, 4, 24) 

当然,在30天月份的第31天或从2月份失踪的日子里(需要照顾闰年),你需要小心,但这也很容易:

 >>> a_date = datetime.date(2016, 3, 31) >>> last_day_previous_month = a_date - datetime.timedelta(days=a_date.day) >>> a_date_minus_month = ( ... last_day_previous_month.replace(day=a_date.day) ... if a_date.day < last_day_previous_month.day ... else last_day_previous_month ... ) >>> a_date_minus_month datetime.date(2016, 2, 29) 

这是一些代码来做到这一点。 没有尝试过自己…

 def add_one_month(t): """Return a `datetime.date` or `datetime.datetime` (as given) that is one month earlier. Note that the resultant day of the month might change if the following month has fewer days: >>> add_one_month(datetime.date(2010, 1, 31)) datetime.date(2010, 2, 28) """ import datetime one_day = datetime.timedelta(days=1) one_month_later = t + one_day while one_month_later.month == t.month: # advance to start of next month one_month_later += one_day target_month = one_month_later.month while one_month_later.day < t.day: # advance to appropriate day one_month_later += one_day if one_month_later.month != target_month: # gone too far one_month_later -= one_day break return one_month_later def subtract_one_month(t): """Return a `datetime.date` or `datetime.datetime` (as given) that is one month later. Note that the resultant day of the month might change if the following month has fewer days: >>> subtract_one_month(datetime.date(2010, 3, 31)) datetime.date(2010, 2, 28) """ import datetime one_day = datetime.timedelta(days=1) one_month_earlier = t - one_day while one_month_earlier.month == t.month or one_month_earlier.day > t.day: one_month_earlier -= one_day return one_month_earlier 

给定一个(年,月)元组,月份从1-12,尝试这个:

 >>> from datetime import datetime >>> today = datetime.today() >>> today datetime.datetime(2010, 8, 6, 10, 15, 21, 310000) >>> thismonth = today.year, today.month >>> thismonth (2010, 8) >>> lastmonth = lambda (yr,mo): [(y,m+1) for y,m in (divmod((yr*12+mo-2), 12),)][0] >>> lastmonth(thismonth) (2010, 7) >>> lastmonth( (2010,1) ) (2009, 12) 

假设每年有12个月。

 def month_sub(year, month, sub_month): result_month = 0 result_year = 0 if month > (sub_month % 12): result_month = month - (sub_month % 12) result_year = year - (sub_month / 12) else: result_month = 12 - (sub_month % 12) + month result_year = year - (sub_month / 12 + 1) return (result_year, result_month) >>> month_sub(2015, 7, 1) (2015, 6) >>> month_sub(2015, 7, -1) (2015, 8) >>> month_sub(2015, 7, 13) (2014, 6) >>> month_sub(2015, 7, -14) (2016, 9) 

我用下面的代码回来n从一个特定的date几个月:

 your_date = datetime.strptime(input_date, "%Y-%m-%d") #to convert date(2016-01-01) to timestamp start_date=your_date #start from current date #Calculate Month for i in range(0,n): #n = number of months you need to go back start_date=start_date.replace(day=1) #1st day of current month start_date=start_date-timedelta(days=1) #last day of previous month #Calculate Day if(start_date.day>your_date.day): start_date=start_date.replace(day=your_date.day) print start_date 

例如:inputdate= 28/12/2015计算6个月前的date。

我)计算月:这一步将给你start_date截至30/06/2015。
请注意 ,在计算月份步骤后,您将获得所需月份的最后一天。

II)计算date: 如果(start_date.day> your_date.day)检查在input_date中的date是否存在于所需月份中, 这处理inputdate为31(或30)且所需月份less于31(或feb时为30)天的条件。 它也处理闰年的情况(2月)。 在这一步之后,您将获得2015年6月28日的结果

如果这个条件不满足,start_date仍然是上个月的最后一个date。 因此,如果您以2015年12月31日作为inputdate,并希望6个月前的date,它会给你30/06/2015