Answers:
试试这个:
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])
dt - timedelta(days=dt.day)按最初的措辞来完成所需的操作,尽管听起来像他们希望能够减去任意几个月的时间,但这有点困难。
您可以使用第三方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
month和monthsdateutil 感到困惑。用参数减法month不起作用,但months有效 In [23]: created_datetime__lt - relativedelta(months=1) Out[23]: datetime.datetime(2016, 11, 29, 0, 0, tzinfo=<StaticTzInfo 'Etc/GMT-8'>) In [24]: created_datetime__lt - relativedelta(month=1) Out[24]: datetime.datetime(2016, 1, 29, 0, 0, tzinfo=<StaticTzInfo 'Etc/GMT-8'>)
months将相差1个月。使用month会将月份设置为1(例如1月),而不考虑输入的月份。
将原始问题编辑为“上个月的任何日期时间对象”后,您可以轻松地做到这一点,只需从该月的第一天减去1天即可。
from datetime import datetime, timedelta
def a_day_in_previous_month(dt):
return dt.replace(day=1) - timedelta(days=1)
dt.replace(day=1) - timedelta(1)
dt - timedelta(days=dt.day)
邓肯答案的一种变体(我没有足够的声誉来发表评论),它使用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 获取本月最后一天的月份范围的信息
矢量化的熊猫解决方案非常简单:
df['date'] - pd.DateOffset(months=1)
pandas。谢谢!
如果只有timedelta在构造函数中有一个month参数。那么最简单的方法是什么?
如果从3月30日的日期中减去一个月,您希望结果是什么?这就是增加或减少月份的问题:月份的长度不同!在一些应用程序中的例外是在这种情况下适当的,在别人“前一个月的最后一天”是OK的使用(但是这是真正疯狂的算术,减去一个月的时候再加入一个月是不是整体无操作!) ,但在其他日期中,您还需要保留一些有关事实的指示,例如:“我是说2月28日,但我真的希望2月30日(如果存在的话)”,以便对日期加上或减去另一个月可以再次设置正确的东西(后者显然需要一个自定义类,其中包含数据和其他内容)。
不可能有所有应用程序都可以容忍的真正解决方案,并且您还没有告诉我们此可怜的操作的语义对您的特定应用程序有什么需求,因此我们在这里没有提供更多帮助。
datetime模块假设一天正好是24小时(没有leap秒)
我认为简单的方法是像这样使用Pandas的DateOffset:
import pandas as pd
date_1 = pd.to_datetime("2013-03-31", format="%Y-%m-%d") - pd.DateOffset(months=1)
结果将是日期时间对象
如果您想要的只是上个月的任何一天,那么您可以做的最简单的事情就是从当前日期减去天数,这将为您提供上个月的最后一天。
例如,从任何日期开始:
>>> import datetime
>>> today = datetime.date.today()
>>> today
datetime.date(2016, 5, 24)
减去当前日期的天数,我们得到:
>>> 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月之后缺少的日期(并注意leap年),但这也很容易做到:
>>> 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)
我将其用于第4季度从10月1日开始的政府财政年度。请注意,我将日期转换为季度,也将其撤消。
import pandas as pd
df['Date'] = '1/1/2020'
df['Date'] = pd.to_datetime(df['Date']) #returns 2020-01-01
df['NewDate'] = df.Date - pd.DateOffset(months=3) #returns 2019-10-01 <---- answer
# For fun, change it to FY Quarter '2019Q4'
df['NewDate'] = df['NewDate'].dt.year.astype(str) + 'Q' + df['NewDate'].dt.quarter.astype(str)
# Convert '2019Q4' back to 2019-10-01
df['NewDate'] = pd.to_datetime(df.NewDate)
这是一些执行此操作的代码。我自己还没有尝试过...
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个月:
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
例如:输入日期= 2015年12月28日计算前6个月的日期。
I)计算月份:此步骤会将开始日期定为2015年6月30日。
请注意,在“计算月份”步骤之后,您将获得所需月份的最后一天。
II)CALCULATE DAY:条件if(start_date.day> your_date.day) 检查所需日期中是否存在从input_date开始的日期。这可以处理输入日期为31(或30)且所需月份少于31(或2月为30)天的情况。它也处理leap年情况(2月)。完成此步骤后,您将获得结果28/06/2015
如果不满足此条件,则start_date保留上个月的最后日期。因此,如果您输入2015年12月31日为输入日期,并希望前6个月为输入日期,则会给您2015年6月30日
您可以使用以下给定的功能获取X个月之前/之后的日期。
从日期时间导入日期开始
def next_month(给定日期,月份):
yyyy = int((((给定日期。年* 12 +给定日期。月)+月)/ 12)
mm = int((((给定日期。年* 12 +给定日期。月)+月)%12)
如果mm == 0:
yyyy-= 1
毫米= 12
返回给定的日期。替换(年= yyyy,月=毫米)
如果__name__ ==“ __main__”:
今天= date.today()
打印(今天)
对于[-12,-1,0,1,2,12,20]中的mm:
next_date = next_month(今天,毫米)
打印(下一个日期)
我认为这个答案很容易理解:
def month_delta(dt, delta):
year_delta, month = divmod(dt.month + delta, 12)
if month == 0:
# convert a 0 to december
month = 12
if delta < 0:
# if moving backwards, then it's december of last year
year_delta -= 1
year = dt.year + year_delta
return dt.replace(month=month, year=year)
for delta in range(-20, 21):
print(delta, "->", month_delta(datetime(2011, 1, 1), delta))
-20 -> 2009-05-01 00:00:00
-19 -> 2009-06-01 00:00:00
-18 -> 2009-07-01 00:00:00
-17 -> 2009-08-01 00:00:00
-16 -> 2009-09-01 00:00:00
-15 -> 2009-10-01 00:00:00
-14 -> 2009-11-01 00:00:00
-13 -> 2009-12-01 00:00:00
-12 -> 2010-01-01 00:00:00
-11 -> 2010-02-01 00:00:00
-10 -> 2010-03-01 00:00:00
-9 -> 2010-04-01 00:00:00
-8 -> 2010-05-01 00:00:00
-7 -> 2010-06-01 00:00:00
-6 -> 2010-07-01 00:00:00
-5 -> 2010-08-01 00:00:00
-4 -> 2010-09-01 00:00:00
-3 -> 2010-10-01 00:00:00
-2 -> 2010-11-01 00:00:00
-1 -> 2010-12-01 00:00:00
0 -> 2011-01-01 00:00:00
1 -> 2011-02-01 00:00:00
2 -> 2011-03-01 00:00:00
3 -> 2011-04-01 00:00:00
4 -> 2011-05-01 00:00:00
5 -> 2011-06-01 00:00:00
6 -> 2011-07-01 00:00:00
7 -> 2011-08-01 00:00:00
8 -> 2011-09-01 00:00:00
9 -> 2011-10-01 00:00:00
10 -> 2011-11-01 00:00:00
11 -> 2012-12-01 00:00:00
12 -> 2012-01-01 00:00:00
13 -> 2012-02-01 00:00:00
14 -> 2012-03-01 00:00:00
15 -> 2012-04-01 00:00:00
16 -> 2012-05-01 00:00:00
17 -> 2012-06-01 00:00:00
18 -> 2012-07-01 00:00:00
19 -> 2012-08-01 00:00:00
20 -> 2012-09-01 00:00:00
我刚刚尝试过的最简单方法
from datetime import datetime
from django.utils import timezone
current = timezone.now()
if current.month == 1:
month = 12
else:
month = current.month - 1
current = datetime(current.year, month, current.day)
前段时间,我遇到了以下算法,该算法在a date或上增加和减少月份时效果很好datetime。
CAVEAT:如果day新月份不可用,它将失败。我day == 1总是在约会对象上使用它。
Python 3.x:
def increment_month(d, add=1):
return date(d.year+(d.month+add-1)//12, (d.month+add-1) % 12+1, 1)
对于Python 2.7,请将更改为//12,/12因为这暗示了整数除法。
当脚本开始获取这些有用的全局变量时,我最近在默认文件中使用了此函数:
MONTH_THIS = datetime.date.today()
MONTH_THIS = datetime.date(MONTH_THIS.year, MONTH_THIS.month, 1)
MONTH_1AGO = datetime.date(MONTH_THIS.year+(MONTH_THIS.month-2)//12,
(MONTH_THIS.month-2) % 12+1, 1)
MONTH_2AGO = datetime.date(MONTH_THIS.year+(MONTH_THIS.month-3)//12,
(MONTH_THIS.month-3) % 12+1, 1)
import datetime
date_str = '08/01/2018'
format_str = '%d/%m/%Y'
datetime_obj = datetime.datetime.strptime(date_str, format_str)
datetime_obj.replace(month=datetime_obj.month-1)
简单的解决方案,不需要特殊的库。
您可以像下面这样两行:
now = datetime.now()
last_month = datetime(now.year, now.month - 1, now.day)
记住进口
from datetime import datetime
((date.month+delta-1) % 12)+1作品,并且意味着if not m: m = 12可以将其取下