日付関連プログラムあるあるの「月末」の取得。
結局、 StackOverflow 参考にしたそのままなのですが…メモ。
date - Get Last Day of the Month in Python - Stack Overflow
注意
python あるある なのですが、calendar.py
などという名前でプログラムファイルを作らないこと。標準モジュールの代わりにそれが呼ばれてしまうので。
もし
AttributeError: 'module' object has no attribute 'Calendar'
とか、
AttributeError: 'module' object has no attribute 'monthrange'
とかエラーが出たら、作業ディレクトリに生成されているはずの calendar.pyc
を削除すること。
calendar モジュールを使う方法
例えば 2014年12月の場合。
import calendar
print calendar.monthrange(2014,12)
8.2. calendar — 一般的なカレンダーに関する関数群 — Python 2.7ja1 documentation によると、
calendar.monthrange(year, month)(原文)
year と month で指定された月の一日の曜日と日数を返します。
というわけで、
(0, 31)
と返ってくる。これは、月初の曜日が月曜日 (曜日番号 0 番) で、指定月の日数が 31 日ということ。
なので、
import calendar
_, lastday = calendar.monthrange(2014,12)
print(lastday)
31
で得られるのが指定月の月末の日、ということになる。
datetime.timedelta(days=1) を使う方法
翌月の月初から 1 日を引き算する。
datetime モジュールでは timedelta サブクラスを使うことで加減算や大小比較が算術演算子を使って出来るようになっている。
8.1. datetime — 基本的な日付型および時間型 — Python 2.7ja1 documentation
import datetime
date = datetime.date(2015, 1, 1) - datetime.timedelta(days=1)
print date.day
31
上記どちらかの方法がよさ気では、という感じ。
月初日は次のように求められると思います。
import datetime
dt = datetime.datetime.utcnow()
# datetime.datetime(2017, 11, 26, 20, 51, 59, 745695)
dt.date() - datetime.timedelta(days=dt.day - 1)
# datetime.date(2017, 11, 1)
以上。
ちな Ruby
require 'Date'
puts Date.new(2001,2,-1).day
うお、 1 行かー…。
28
Ruby らしいといえばらしい気もする。
おわり。
追記
前月の末日
from datetime import datetime, timedelta
yesterday = datetime(2018, 3, 29).date()
last_day_of_previous_month = yesterday - timedelta(days=yesterday.day)