私はpythonアプリを数年にわたって3か月ごとに日付をプロットする必要があります。日付は年に4回だけ発生し、日付は毎年同じ日に発生することが重要です可能な限り、日付は可能な限り月の同じ日に発生し、日付はできる限り「3か月」離れていること(これは特にうるう年の移動目標です) )。残念ながら、datetime.timedelta
は月をサポートしていません!
Pythonでこの計算を行うための「標準的な」方法はありますか?
最悪の事態が発生した場合、私はパントして、次のような答えを得るために、日付計算のためのNice組み込みサポートを持っているPostgreSQLに私のアプリに尋ねます:
# select ('2010-11-29'::date + interval '3 months')::date;
date
------------
2011-02-28
(1 row)
正確な日付または「より正確な」日付を探している場合は、おそらく dateutil をチェックアウトすることをお勧めします。
簡単な例:
>>> from dateutil.relativedelta import relativedelta
>>> import datetime
>>> TODAY = datetime.date.today()
>>> TODAY
datetime.date(2012, 3, 6)
ここで、TODAY
に3か月を追加し、その日が正確に一致することを確認します(relativedelta(months=3)
とrelativedelta(month=3)
の動作が異なることに注意してください。これらの例では必ずmonths
を使用してください!).
>>> three_mon_rel = relativedelta(months=3)
>>> TODAY + three_mon_rel
datetime.date(2012, 6, 6)
そして、それは一年を通して一貫したままです。文字通り、3か月ごと、その日(何らかの理由でrelativedelta
を乗算し、datetime.date
オブジェクトに追加するとTypeError
がスローされるため、追加を続けなければなりませんでした):
>>> TODAY + three_mon_rel + three_mon_rel
datetime.date(2012, 9, 6)
>>> TODAY + three_mon_rel + three_mon_rel + three_mon_rel
datetime.date(2012, 12, 6)
>>> TODAY + three_mon_rel + three_mon_rel + three_mon_rel + three_mon_rel
datetime.date(2013, 3, 6)
mVChr の推奨ソリューションは、間違いなく「十分」ですが、時間の経過とともにわずかにドリフトします。
>>> three_mon_timedelta = datetime.timedelta(days=3 * 365/12)
>>> TODAY + three_mon_timedelta
datetime.date(2012, 6, 5)
そして、1年の間、月の日はスライドし続けます:
>>> TODAY + three_mon_timedelta * 2
datetime.date(2012, 9, 4)
>>> TODAY + three_mon_timedelta * 3
datetime.date(2012, 12, 4)
>>> TODAY + three_mon_timedelta * 4
datetime.date(2013, 3, 5)
import datetime
some_date = datetime.date.today()
three_months = datetime.timedelta(3*365/12)
print (some_date + three_months).isoformat()
# => '2012-06-01'
その後、新しい年ごとに元の日付に「正規化」します(2月29日を除く)
ここに良い解決策があります http://www.voidspace.org.uk/python/weblog/Arch_d7_2012_02_25.shtml#e1235
標準的な方法で編集して申し訳ありません...
Python標準ライブラリ、つまりdateutil
などを使用せずに、 'February 31st'問題を解決する:
import datetime
import calendar
def add_months(date, months):
months_count = date.month + months
# Calculate the year
year = date.year + int(months_count / 12)
# Calculate the month
month = (months_count % 12)
if month == 0:
month = 12
# Calculate the day
day = date.day
last_day_of_month = calendar.monthrange(year, month)[1]
if day > last_day_of_month:
day = last_day_of_month
new_date = datetime.date(year, month, day)
return new_date
テスト:
>>>date = datetime.date(2018, 11, 30)
>>>print(date, add_months(date, 3))
(datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))
>>>print(date, add_months(date, 14))
(datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))