回答:
これを試して:
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)
Duncanの回答のバリエーション(コメントする十分な評判がありません)。これは、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)
ベクトル化されたパンダソリューションは非常にシンプルです。
df['date'] - pd.DateOffset(months=1)
pandas。ありがとう!
timedeltaのみがコンストラクタで月の引数を持っていた場合。これを行う最も簡単な方法は何ですか?
たとえば、3月30日の日付から1か月差し引いた結果をどうしますか?これは、月を加算または減算する場合の問題です。月の長さが異なります。一部のアプリケーションでは、そのような場合に例外が適切であり、他の場合には、「前月の最終日」を使用しても問題ありません(ただし、月を減算してから月を追加することは、全体的に無操作ではありません!) 、他の場合では、日付に加えて、事実についての何らかの指示を保持する必要があります。たとえば、「2月28日と言っていますが、2月30日が存在する場合は本当に必要です」ので、それは物事を再び正しく設定できます(そして後者は明らかにデータとその他のものを保持するカスタムクラスを必要とします)。
すべてのアプリケーションに耐えられる実際のソリューションはあり得ません。また、この惨めな操作のセマンティクスに対する特定のアプリのニーズを私たちに教えていないため、ここで提供できるヘルプはそれほど多くありません。
datetimeモジュールは、1日が正確に24時間(うるう秒なし)であると想定しています
簡単な方法は、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日に注意する必要があります。
>>> 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)
これは、Q4が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)月の計算:このステップでは、start_dateが30/06/2015になります。
注意月の計算ステップの後に、必要な月の最終日が表示されることにて。
II)計算日:条件if(start_date.day> your_date.day) 日は、input_dateからの日が必要な月に存在するかどうかをチェックします。これは、入力日付が31(または30)日であり、必要な月が31(または2月の場合は30)日未満である条件を処理します。うるう年ケースにも対応(2月分)。この手順の後、2015年6月28日として結果を取得します
この条件が満たされない場合、start_dateは前月の最後の日付のままになります。したがって、2015年12月31日を入力日として指定し、6か月前の日付が必要な場合は、2015年6月30日になります。
以下の所定の関数を使用して、Xか月の前後の日付を取得できます。
日時インポート日から
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)
mm == 0の場合:
yyyy-= 1
mm = 12
given_date.replace(年= yyyy、月= mm)を返します
__name__ == "__main__"の場合:
今日= date.today()
プリント(今日)
mmの場合[-12、-1、0、1、2、12、20]:
next_date = next_month(今日、mm)
print(next_date)
この答えはかなり読みやすいと思います:
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
一発ギャグ ?
previous_month_date = (current_date - datetime.timedelta(days=current_date.day+1)).replace(day=current_date.day)
少し前に、次のアルゴリズムに出くわしました。これは、dateまたはのいずれかで月を増分および減分するのに非常にうまく機能しますdatetime。
警告: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)
シンプルなソリューションで、特別なライブラリは必要ありません。
((date.month+delta-1) % 12)+1機能し、if not m: m = 12缶が取り除かれることを意味する場合