Python の標準ライブラリを使用して、特定の月の最終日を簡単に判断する (つまり、1 つの関数呼び出し) 方法はありますか?
標準ライブラリがサポートしていない場合、dateutil パッケージはこれをサポートしていますか?
calendar.monthrange
この情報を提供します:
カレンダー。monthrange(year、month)指定された年と月
について、月の最初の日の曜日と月の日数を返します。
>>> import calendar
>>> calendar.monthrange(2002, 1)
(1, 31)
>>> calendar.monthrange(2008, 2) # leap years are handled correctly
(4, 29)
>>> calendar.monthrange(2100, 2) # years divisible by 100 but not 400 aren't leap years
(0, 28)
それで:
calendar.monthrange(year, month)[1]
最も簡単な方法のようです。
モジュールをインポートしたくない場合はcalendar
、単純な 2 ステップの関数を次のようにすることもできます。
import datetime
def last_day_of_month(any_day):
# this will never fail
# get close to the end of the month for any day, and add 4 days 'over'
next_month = any_day.replace(day=28) + datetime.timedelta(days=4)
# subtract the number of remaining 'overage' days to get last day of current month, or said programattically said, the previous day of the first of next month
return next_month - datetime.timedelta(days=next_month.day)
出力:
>>> for month in range(1, 13):
... print last_day_of_month(datetime.date(2012, month, 1))
...
2012-01-31
2012-02-29
2012-03-31
2012-04-30
2012-05-31
2012-06-30
2012-07-31
2012-08-31
2012-09-30
2012-10-31
2012-11-30
2012-12-31
編集:よりクリーンなソリューションについては、@ Blair Conradの回答を参照してください
>>> import datetime
>>> datetime.date(2000, 2, 1) - datetime.timedelta(days=1)
datetime.date(2000, 1, 31)
This is actually pretty easy with dateutil.relativedelta
. day=31
will always always return the last day of the month:
import datetime
from dateutil.relativedelta import relativedelta
date_in_feb = datetime.datetime(2013, 2, 21)
print(datetime.datetime(2013, 2, 21) + relativedelta(day=31)) # End-of-month
# datetime.datetime(2013, 2, 28, 0, 0)
Install dateutil
with
pip install python-datetutil
編集:私の他の回答を参照してください。これは、これよりも優れた実装を備えています。これは、誰かが「自分で計算する」方法に興味がある場合に備えて、ここに残しておきます。
@John Millikin は、翌月の最初の日を計算するという複雑さを加えて、良い答えを出します。
以下は特にエレガントではありませんが、特定の日付が存在する月の最後の日を把握するには、次を試してください。
def last_day_of_month(date):
if date.month == 12:
return date.replace(day=31)
return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)
>>> last_day_of_month(datetime.date(2002, 1, 17))
datetime.date(2002, 1, 31)
>>> last_day_of_month(datetime.date(2002, 12, 9))
datetime.date(2002, 12, 31)
>>> last_day_of_month(datetime.date(2008, 2, 14))
datetime.date(2008, 2, 29)
あなたを使用dateutil.relativedelta
すると、次のように月の最終日が取得されます。
from dateutil.relativedelta import relativedelta
last_date_of_month = datetime(mydate.year, mydate.month, 1) + relativedelta(months=1, days=-1)
アイデアは、月の最初の日を取得し、relativedelta
1 か月先に移動して 1 日戻すために使用することで、必要な月の最後の日を取得します。
from datetime import timedelta
(any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1)
別の解決策は、次のようなことです。
from datetime import datetime
def last_day_of_month(year, month):
""" Work out the last day of the month """
last_days = [31, 30, 29, 28, 27]
for i in last_days:
try:
end = datetime(year, month, i)
except ValueError:
continue
else:
return end.date()
return None
そして、次のように関数を使用します。
>>>
>>> last_day_of_month(2008, 2)
datetime.date(2008, 2, 29)
>>> last_day_of_month(2009, 2)
datetime.date(2009, 2, 28)
>>> last_day_of_month(2008, 11)
datetime.date(2008, 11, 30)
>>> last_day_of_month(2008, 12)
datetime.date(2008, 12, 31)
>>> import datetime
>>> import calendar
>>> date = datetime.datetime.now()
>>> print date
2015-03-06 01:25:14.939574
>>> print date.replace(day = 1)
2015-03-01 01:25:14.939574
>>> print date.replace(day = calendar.monthrange(date.year, date.month)[1])
2015-03-31 01:25:14.939574
月の最後の日付を取得するには、次のようにします。
from datetime import date, timedelta
import calendar
last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1])
ここで何をしているのかを説明するために、2 つの部分に分けて説明します。
まず、ブレア・コンラッドがすでに彼の解決策について言及しているmonthrangeを使用して、現在の月の日数を取得しています。
calendar.monthrange(date.today().year, date.today().month)[1]
2番目は、置換の助けを借りて行う最後の日付自体を取得しています。
>>> date.today()
datetime.date(2017, 1, 3)
>>> date.today().replace(day=31)
datetime.date(2017, 1, 31)
そして、上で述べたようにそれらを組み合わせると、動的なソリューションが得られます。
パンダを使おう!
def isMonthEnd(date):
return date + pd.offsets.MonthEnd(0) == date
isMonthEnd(datetime(1999, 12, 31))
True
isMonthEnd(pd.Timestamp('1999-12-31'))
True
isMonthEnd(pd.Timestamp(1965, 1, 10))
False
import datetime
now = datetime.datetime.now()
start_month = datetime.datetime(now.year, now.month, 1)
date_on_next_month = start_month + datetime.timedelta(35)
start_next_month = datetime.datetime(date_on_next_month.year, date_on_next_month.month, 1)
last_day_month = start_next_month - datetime.timedelta(1)
私にとって簡単な方法は、パンダを使用することです(2行のソリューション):
from datetime import datetime
import pandas as pd
firstday_month = datetime(year, month, 1)
lastday_month = firstday_month + pd.offsets.MonthEnd(1)
もう 1 つの方法は、月の最初の日を取り、1 か月を加算して 1 日を割り引くことです。
from datetime import datetime
import pandas as pd
firstday_month = datetime(year, month, 1)
lastday_month = firstday_month + pd.DateOffset(months=1) - pd.DateOffset(days=1)
終了日は自分で計算できます。簡単なロジックは、翌月の start_date から 1 日を引くことです。:)
カスタムメソッドを書いて、
import datetime
def end_date_of_a_month(date):
start_date_of_this_month = date.replace(day=1)
month = start_date_of_this_month.month
year = start_date_of_this_month.year
if month == 12:
month = 1
year += 1
else:
month += 1
next_month_start_date = start_date_of_this_month.replace(month=month, year=year)
this_month_end_date = next_month_start_date - datetime.timedelta(days=1)
return this_month_end_date
呼び出し、
end_date_of_a_month(datetime.datetime.now().date())
今月の最終日を返します。この関数に任意の日付を渡します。その月の最終日を返します。
私にとっては、最も簡単な方法です:
selected_date = date(some_year, some_month, some_day)
if selected_date.month == 12: # December
last_day_selected_month = date(selected_date.year, selected_date.month, 31)
else:
last_day_selected_month = date(selected_date.year, selected_date.month + 1, 1) - timedelta(days=1)
それが私のやり方です - たった2行の関数です:
from dateutil.relativedelta import relativedelta
def last_day_of_month(date):
return date.replace(day=1) + relativedelta(months=1) - relativedelta(days=1)
例:
from datetime import date
print(last_day_of_month(date.today()))
>> 2021-09-30
これは主要な問題には対応していませんが、月の最後の平日calendar.monthcalendar
を取得する 1 つの優れたトリックは、月曜日を最初の列とし、日曜日を最後の列として構成された日付の行列を返すを使用することです。
# Some random date.
some_date = datetime.date(2012, 5, 23)
# Get last weekday
last_weekday = np.asarray(calendar.monthcalendar(some_date.year, some_date.month))[:,0:-2].ravel().max()
print last_weekday
31
全体[0:-2]
は、週末のコラムを削って捨てることです。月外の日付は 0 で示されるため、max は実質的にそれらを無視します。
の使用は厳密には必要ありませんが、計算する軸が指定されていない場合に配列を平坦化するという単なる規則numpy.ravel
に頼るのは嫌いです。numpy.ndarray.max
もっと簡単に:
import datetime
now = datetime.datetime.now()
datetime.date(now.year, 1 if now.month==12 else now.month+1, 1) - datetime.timedelta(days=1)
私はこの方法を好みます
import datetime
import calendar
date=datetime.datetime.now()
month_end_date=datetime.datetime(date.year,date.month,1) + datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1] - 1)
import calendar
from time import gmtime, strftime
calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]
出力:
31
これにより、現在の月が何であれ、最終日が出力されます。この例では、2016 年 5 月 15 日でした。したがって、出力は異なる場合がありますが、出力は現在の月と同じ日数になります。毎日 cron ジョブを実行して月の最終日を確認したい場合に最適です。
そう:
import calendar
from time import gmtime, strftime
lastDay = calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]
today = strftime("%d", gmtime())
lastDay == today
出力:
False
月の最終日でない限り。
独自の小さな関数を作成したい場合、これは良い出発点です:
def eomday(year, month):
"""returns the number of days in a given month"""
days_per_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
d = days_per_month[month - 1]
if month == 2 and (year % 4 == 0 and year % 100 != 0 or year % 400 == 0):
d = 29
return d
そのためには、うるう年のルールを知っておく必要があります。