Python月初・月末(初日・最終日)、最終X曜日の日付を取得する方法
Pythonで月の初日・最終日、および最終X曜日(最終月曜日、最終金曜日など)の日付を取得する方法を詳しく解説します。実用的なサンプルコードとともに様々なパターンを学びましょう。
月初・月末の基本取得
基本的な月初・月末の取得
from datetime import date, datetime, timedelta
import calendar
def get_month_first_last(year, month):
"""指定年月の初日と最終日を取得"""
# 月初(1日)
first_day = date(year, month, 1)
# 月末(最終日)
_, last_day_num = calendar.monthrange(year, month)
last_day = date(year, month, last_day_num)
return {
'first_day': first_day,
'last_day': last_day,
'days_in_month': last_day_num
}
# 使用例
result = get_month_first_last(2024, 2)
print(f"2024年2月")
print(f"初日: {result['first_day']}")
print(f"最終日: {result['last_day']}")
print(f"日数: {result['days_in_month']}日")
現在月の初日・最終日
from datetime import date, datetime
import calendar
def get_current_month_bounds():
"""現在月の初日と最終日を取得"""
today = date.today()
year = today.year
month = today.month
first_day = date(year, month, 1)
_, last_day_num = calendar.monthrange(year, month)
last_day = date(year, month, last_day_num)
return {
'today': today,
'first_day': first_day,
'last_day': last_day,
'days_remaining': (last_day - today).days
}
# 使用例
current_bounds = get_current_month_bounds()
print(f"今日: {current_bounds['today']}")
print(f"今月の初日: {current_bounds['first_day']}")
print(f"今月の最終日: {current_bounds['last_day']}")
print(f"月末まで: {current_bounds['days_remaining']}日")
前月・次月の初日・最終日
from datetime import date, timedelta
import calendar
def get_previous_month_bounds(reference_date=None):
"""前月の初日・最終日を取得"""
if reference_date is None:
reference_date = date.today()
# 前月の年月を計算
if reference_date.month == 1:
prev_year = reference_date.year - 1
prev_month = 12
else:
prev_year = reference_date.year
prev_month = reference_date.month - 1
first_day = date(prev_year, prev_month, 1)
_, last_day_num = calendar.monthrange(prev_year, prev_month)
last_day = date(prev_year, prev_month, last_day_num)
return {
'first_day': first_day,
'last_day': last_day,
'year': prev_year,
'month': prev_month
}
def get_next_month_bounds(reference_date=None):
"""次月の初日・最終日を取得"""
if reference_date is None:
reference_date = date.today()
# 次月の年月を計算
if reference_date.month == 12:
next_year = reference_date.year + 1
next_month = 1
else:
next_year = reference_date.year
next_month = reference_date.month + 1
first_day = date(next_year, next_month, 1)
_, last_day_num = calendar.monthrange(next_year, next_month)
last_day = date(next_year, next_month, last_day_num)
return {
'first_day': first_day,
'last_day': last_day,
'year': next_year,
'month': next_month
}
# 使用例
prev_month = get_previous_month_bounds()
next_month = get_next_month_bounds()
print(f"前月: {prev_month['first_day']} ~ {prev_month['last_day']}")
print(f"次月: {next_month['first_day']} ~ {next_month['last_day']}")
最終X曜日の取得
基本的な最終曜日の取得
from datetime import date, timedelta
import calendar
def get_last_weekday_of_month(year, month, weekday):
"""指定年月の最終X曜日を取得
Args:
year: 年
month: 月
weekday: 曜日 (0=月曜日, 1=火曜日, ..., 6=日曜日)
"""
# 月の最終日を取得
_, last_day_num = calendar.monthrange(year, month)
last_day = date(year, month, last_day_num)
# 最終日から遡って指定曜日を探す
days_back = (last_day.weekday() - weekday) % 7
target_date = last_day - timedelta(days=days_back)
return target_date
# 使用例
year = 2024
month = 1
weekdays = ['月', '火', '水', '木', '金', '土', '日']
for i, weekday_name in enumerate(weekdays):
last_weekday = get_last_weekday_of_month(year, month, i)
print(f"最終{weekday_name}曜日: {last_weekday}")
複数月の最終曜日を一括取得
def get_last_weekdays_for_year(year, weekday):
"""年間の各月の最終X曜日を取得"""
last_weekdays = []
for month in range(1, 13):
last_weekday = get_last_weekday_of_month(year, month, weekday)
last_weekdays.append({
'year': year,
'month': month,
'date': last_weekday,
'day': last_weekday.day
})
return last_weekdays
# 使用例:2024年の各月の最終金曜日
last_fridays = get_last_weekdays_for_year(2024, 4) # 4 = 金曜日
print("=== 2024年 各月の最終金曜日 ===")
for info in last_fridays:
print(f"{info['month']:2d}月: {info['date']} ({info['day']:2d}日)")
営業日としての最終平日
def get_last_business_day_of_month(year, month):
"""月の最終営業日を取得(土日を除く)"""
# 月の最終日から遡って平日を探す
_, last_day_num = calendar.monthrange(year, month)
last_day = date(year, month, last_day_num)
# 土日でない日を探す
while last_day.weekday() >= 5: # 5=土曜日, 6=日曜日
last_day -= timedelta(days=1)
return last_day
def get_first_business_day_of_month(year, month):
"""月の最初の営業日を取得(土日を除く)"""
first_day = date(year, month, 1)
# 土日でない日を探す
while first_day.weekday() >= 5:
first_day += timedelta(days=1)
return first_day
# 使用例
year = 2024
month = 1
first_business = get_first_business_day_of_month(year, month)
last_business = get_last_business_day_of_month(year, month)
print(f"{year}年{month}月")
print(f"最初の営業日: {first_business}")
print(f"最終営業日: {last_business}")
高度な日付計算
N番目の曜日の取得
def get_nth_weekday_of_month(year, month, weekday, n):
"""月のN番目の指定曜日を取得
Args:
year: 年
month: 月
weekday: 曜日 (0=月曜日, ..., 6=日曜日)
n: 何番目か (1=第1, 2=第2, ..., -1=最後, -2=最後から2番目)
"""
if n > 0:
# N番目を前から探す
first_day = date(year, month, 1)
days_until_weekday = (weekday - first_day.weekday()) % 7
first_occurrence = first_day + timedelta(days=days_until_weekday)
target_date = first_occurrence + timedelta(weeks=n-1)
# 月を超えていないかチェック
if target_date.month != month:
return None
return target_date
elif n < 0:
# 最後からN番目を探す
last_weekday = get_last_weekday_of_month(year, month, weekday)
target_date = last_weekday + timedelta(weeks=n+1)
# 月を下回っていないかチェック
if target_date.month != month or target_date.year != year:
return None
return target_date
else:
return None
# 使用例
year = 2024
month = 1
print(f"=== {year}年{month}月の月曜日 ===")
for i in range(1, 6):
nth_monday = get_nth_weekday_of_month(year, month, 0, i) # 0 = 月曜日
if nth_monday:
print(f"第{i}月曜日: {nth_monday}")
else:
print(f"第{i}月曜日: なし")
print(f"\n最後から数えた月曜日:")
last_monday = get_nth_weekday_of_month(year, month, 0, -1)
second_last_monday = get_nth_weekday_of_month(year, month, 0, -2)
print(f"最終月曜日: {last_monday}")
print(f"最後から2番目: {second_last_monday}")
月の境界日の詳細情報
def get_month_boundary_info(year, month):
"""月の境界日の詳細情報を取得"""
# 基本情報
first_day = date(year, month, 1)
_, last_day_num = calendar.monthrange(year, month)
last_day = date(year, month, last_day_num)
# 曜日名
weekday_names = ['月', '火', '水', '木', '金', '土', '日']
# 営業日情報
first_business = get_first_business_day_of_month(year, month)
last_business = get_last_business_day_of_month(year, month)
# 週末情報
first_weekend = None
last_weekend = None
# 最初の週末を探す
current = first_day
while current.month == month:
if current.weekday() >= 5: # 土日
first_weekend = current
break
current += timedelta(days=1)
# 最後の週末を探す
current = last_day
while current.month == month:
if current.weekday() >= 5: # 土日
last_weekend = current
break
current -= timedelta(days=1)
return {
'year': year,
'month': month,
'first_day': {
'date': first_day,
'weekday': weekday_names[first_day.weekday()],
'is_weekend': first_day.weekday() >= 5
},
'last_day': {
'date': last_day,
'weekday': weekday_names[last_day.weekday()],
'is_weekend': last_day.weekday() >= 5
},
'first_business_day': first_business,
'last_business_day': last_business,
'first_weekend': first_weekend,
'last_weekend': last_weekend,
'total_days': last_day_num
}
# 使用例
boundary_info = get_month_boundary_info(2024, 1)
print(f"=== {boundary_info['year']}年{boundary_info['month']}月 境界情報 ===")
print(f"初日: {boundary_info['first_day']['date']} ({boundary_info['first_day']['weekday']})")
print(f"最終日: {boundary_info['last_day']['date']} ({boundary_info['last_day']['weekday']})")
print(f"最初の営業日: {boundary_info['first_business_day']}")
print(f"最終営業日: {boundary_info['last_business_day']}")
print(f"最初の週末: {boundary_info['first_weekend']}")
print(f"最後の週末: {boundary_info['last_weekend']}")
実用的な応用例
給与支払日の計算
def calculate_salary_payment_dates(year):
"""年間の給与支払日を計算(月末営業日)"""
payment_dates = []
for month in range(1, 13):
payment_date = get_last_business_day_of_month(year, month)
payment_info = {
'month': month,
'payment_date': payment_date,
'day_of_month': payment_date.day,
'weekday': ['月', '火', '水', '木', '金', '土', '日'][payment_date.weekday()]
}
payment_dates.append(payment_info)
return payment_dates
# 使用例
salary_dates = calculate_salary_payment_dates(2024)
print("=== 2024年 給与支払予定日(月末営業日)===")
for info in salary_dates:
print(f"{info['month']:2d}月: {info['payment_date']} ({info['weekday']})")
会議日程の自動設定
def schedule_monthly_meetings(year, weekday, week_number):
"""毎月の定期会議日程を設定
Args:
year: 年
weekday: 曜日 (0=月曜日, ..., 6=日曜日)
week_number: 第何週 (1-4, または -1で最終週)
"""
meeting_schedule = []
weekday_names = ['月', '火', '水', '木', '金', '土', '日']
for month in range(1, 13):
meeting_date = get_nth_weekday_of_month(year, month, weekday, week_number)
if meeting_date:
meeting_info = {
'month': month,
'date': meeting_date,
'weekday': weekday_names[weekday],
'week_description': f"第{week_number}週" if week_number > 0 else "最終週"
}
meeting_schedule.append(meeting_info)
return meeting_schedule
# 使用例:毎月第2火曜日の会議
meetings = schedule_monthly_meetings(2024, 1, 2) # 1=火曜日, 2=第2週
print("=== 2024年 月例会議日程(第2火曜日)===")
for meeting in meetings:
print(f"{meeting['month']:2d}月: {meeting['date']} ({meeting['weekday']})")
四半期末日の計算
def get_quarter_end_dates(year):
"""四半期末日を取得"""
quarters = [
{'quarter': 'Q1', 'month': 3},
{'quarter': 'Q2', 'month': 6},
{'quarter': 'Q3', 'month': 9},
{'quarter': 'Q4', 'month': 12}
]
quarter_ends = []
for quarter_info in quarters:
month = quarter_info['month']
_, last_day_num = calendar.monthrange(year, month)
quarter_end = date(year, month, last_day_num)
# 四半期末営業日も計算
business_end = get_last_business_day_of_month(year, month)
quarter_data = {
'quarter': quarter_info['quarter'],
'calendar_end': quarter_end,
'business_end': business_end,
'days_difference': (quarter_end - business_end).days
}
quarter_ends.append(quarter_data)
return quarter_ends
# 使用例
quarter_ends = get_quarter_end_dates(2024)
print("=== 2024年 四半期末日 ===")
for quarter in quarter_ends:
print(f"{quarter['quarter']}: {quarter['calendar_end']} "
f"(営業日: {quarter['business_end']})")
祝日を考慮した営業日計算
def get_business_day_with_holidays(year, month, holidays=None):
"""祝日を考慮した営業日計算"""
if holidays is None:
# 簡略化した日本の祝日(一部)
holidays = [
date(year, 1, 1), # 元日
date(year, 2, 11), # 建国記念の日
date(year, 4, 29), # 昭和の日
date(year, 5, 3), # 憲法記念日
date(year, 5, 4), # みどりの日
date(year, 5, 5), # こどもの日
]
# 月の範囲を取得
first_day = date(year, month, 1)
_, last_day_num = calendar.monthrange(year, month)
last_day = date(year, month, last_day_num)
# 最初の営業日を取得(祝日考慮)
first_business = first_day
while (first_business.weekday() >= 5 or # 週末
first_business in holidays): # 祝日
first_business += timedelta(days=1)
if first_business.month != month:
first_business = None
break
# 最後の営業日を取得(祝日考慮)
last_business = last_day
while (last_business.weekday() >= 5 or # 週末
last_business in holidays): # 祝日
last_business -= timedelta(days=1)
if last_business.month != month:
last_business = None
break
# 営業日数をカウント
business_days_count = 0
current = first_day
while current <= last_day:
if (current.weekday() < 5 and # 平日
current not in holidays): # 祝日でない
business_days_count += 1
current += timedelta(days=1)
return {
'first_business_day': first_business,
'last_business_day': last_business,
'business_days_count': business_days_count,
'holidays_in_month': [h for h in holidays if h.month == month and h.year == year]
}
# 使用例
business_info = get_business_day_with_holidays(2024, 1)
print("=== 2024年1月 営業日情報(祝日考慮)===")
print(f"最初の営業日: {business_info['first_business_day']}")
print(f"最後の営業日: {business_info['last_business_day']}")
print(f"営業日数: {business_info['business_days_count']}日")
print(f"月内の祝日: {business_info['holidays_in_month']}")
月次レポート生成用の日付取得
def generate_monthly_report_dates(year, month):
"""月次レポート用の重要日付を生成"""
# 基本的な境界日
first_day = date(year, month, 1)
_, last_day_num = calendar.monthrange(year, month)
last_day = date(year, month, last_day_num)
# 営業日
first_business = get_first_business_day_of_month(year, month)
last_business = get_last_business_day_of_month(year, month)
# 月の中間点
mid_day = date(year, month, last_day_num // 2)
# 各週の最終営業日
weekly_ends = []
month_calendar = calendar.monthcalendar(year, month)
for week in month_calendar:
# 週の最後の有効な日を取得
week_days = [day for day in week if day != 0]
if week_days:
week_end = date(year, month, week_days[-1])
# 営業日でない場合は前の営業日を探す
while week_end.weekday() >= 5:
week_end -= timedelta(days=1)
if week_end.month != month:
week_end = None
break
if week_end:
weekly_ends.append(week_end)
report_dates = {
'report_period': f"{year}年{month}月",
'period_start': first_day,
'period_end': last_day,
'business_period_start': first_business,
'business_period_end': last_business,
'mid_month': mid_day,
'weekly_business_ends': weekly_ends,
'total_days': last_day_num,
'business_days': len([d for d in weekly_ends if d is not None])
}
return report_dates
# 使用例
report_dates = generate_monthly_report_dates(2024, 1)
print(f"=== {report_dates['report_period']} レポート用日付 ===")
print(f"期間: {report_dates['period_start']} ~ {report_dates['period_end']}")
print(f"営業期間: {report_dates['business_period_start']} ~ {report_dates['business_period_end']}")
print(f"月中間: {report_dates['mid_month']}")
print("週次営業日終了:")
for i, week_end in enumerate(report_dates['weekly_business_ends'], 1):
print(f" 第{i}週: {week_end}")
複数月の比較分析
def compare_multiple_months(year, months):
"""複数月の境界日情報を比較"""
comparison_data = []
for month in months:
month_info = get_month_boundary_info(year, month)
# 追加の分析情報
first_day = month_info['first_day']['date']
last_day = month_info['last_day']['date']
# 週末の日数計算
weekend_count = 0
current = first_day
while current <= last_day:
if current.weekday() >= 5:
weekend_count += 1
current += timedelta(days=1)
comparison_info = {
'month': month,
'first_day_weekday': month_info['first_day']['weekday'],
'last_day_weekday': month_info['last_day']['weekday'],
'total_days': month_info['total_days'],
'weekend_days': weekend_count,
'business_days': month_info['total_days'] - weekend_count,
'starts_weekend': month_info['first_day']['is_weekend'],
'ends_weekend': month_info['last_day']['is_weekend']
}
comparison_data.append(comparison_info)
return comparison_data
# 使用例:第1四半期の比較
q1_months = [1, 2, 3]
q1_comparison = compare_multiple_months(2024, q1_months)
print("=== 2024年第1四半期 月別比較 ===")
print("月 初日曜日 最終日曜日 総日数 営業日 週末日")
print("-" * 45)
for info in q1_comparison:
print(f"{info['month']:2d}月 {info['first_day_weekday']:>4} "
f"{info['last_day_weekday']:>6} {info['total_days']:>4}日 "
f"{info['business_days']:>4}日 {info['weekend_days']:>4}日")
日付計算のユーティリティクラス
class MonthBoundaryCalculator:
def __init__(self):
self.weekday_names = ['月', '火', '水', '木', '金', '土', '日']
def get_month_info(self, year, month):
"""月の包括的な情報を取得"""
return {
'boundaries': get_month_first_last(year, month),
'business_days': {
'first': get_first_business_day_of_month(year, month),
'last': get_last_business_day_of_month(year, month)
},
'last_weekdays': {
name: get_last_weekday_of_month(year, month, i)
for i, name in enumerate(self.weekday_names)
}
}
def get_year_summary(self, year):
"""年間の月境界情報サマリー"""
year_data = []
for month in range(1, 13):
month_info = self.get_month_info(year, month)
summary = {
'month': month,
'days': month_info['boundaries']['days_in_month'],
'first_business': month_info['business_days']['first'],
'last_business': month_info['business_days']['last'],
'last_friday': month_info['last_weekdays']['金']
}
year_data.append(summary)
return year_data
# 使用例
calculator = MonthBoundaryCalculator()
year_summary = calculator.get_year_summary(2024)
print("=== 2024年 年間サマリー ===")
print("月 日数 初回営業日 最終営業日 最終金曜日")
print("-" * 50)
for summary in year_summary:
print(f"{summary['month']:2d}月 {summary['days']:2d}日 "
f"{summary['first_business']} {summary['last_business']} "
f"{summary['last_friday']}")
まとめ
- 月初・月末:
date(year, month, 1)とcalendar.monthrange()で簡単取得 - 最終X曜日:月末から逆算して指定曜日を検索
- 営業日計算:週末と祝日を考慮した実用的な実装
- 応用例:給与日、会議日程、四半期末、レポート生成
- ユーティリティ:再利用可能なクラス設計
これらの方法を活用することで、ビジネスアプリケーションでの複雑な日付計算が効率的に実装できます。
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座
