Python月の日数・週数を取得する方法【calendar活用完全ガイド】

 

Pythonで指定した月の日数や週数を取得する方法を、calendarモジュールとdatetimeモジュールを使用して詳しく解説します。うるう年の考慮やISO週番号の取得方法も含めて学びましょう。

月の日数を取得する基本方法

calendarモジュールを使用

import calendar

# 指定した年月の日数を取得
year = 2024
month = 2

# monthrangeで月の情報を取得
weekday, days = calendar.monthrange(year, month)
print(f"{year}年{month}月の日数: {days}日")  # 29日(うるう年)
print(f"1日の曜日: {weekday} (0=月曜日)")

# 複数の月の日数を一括取得
months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
for m in months:
    _, days = calendar.monthrange(year, m)
    print(f"{m}月: {days}日")

datetimeモジュールを使用

from datetime import date, timedelta

def get_days_in_month(year, month):
    """指定した年月の日数を取得"""
    # 次の月の1日から1日を引く
    if month == 12:
        next_month = date(year + 1, 1, 1)
    else:
        next_month = date(year, month + 1, 1)
    
    last_day = next_month - timedelta(days=1)
    return last_day.day

# 使用例
year = 2024
month = 2
days = get_days_in_month(year, month)
print(f"{year}年{month}月の日数: {days}日")

月末日を直接取得

from datetime import date, datetime
import calendar

def get_last_day_of_month(year, month):
    """月の最終日を取得"""
    _, last_day = calendar.monthrange(year, month)
    return date(year, month, last_day)

def get_month_info(year, month):
    """月の詳細情報を取得"""
    first_day = date(year, month, 1)
    last_day = get_last_day_of_month(year, month)
    
    return {
        'year': year,
        'month': month,
        'first_day': first_day,
        'last_day': last_day,
        'days_count': last_day.day,
        'first_weekday': first_day.weekday(),
        'last_weekday': last_day.weekday()
    }

# 使用例
info = get_month_info(2024, 2)
print(f"月情報: {info}")

月の週数を取得する方法

calendarモジュールで週数計算

import calendar

def get_weeks_in_month(year, month):
    """月の週数を取得"""
    month_calendar = calendar.monthcalendar(year, month)
    return len(month_calendar)

def get_detailed_weeks_info(year, month):
    """月の週情報を詳細に取得"""
    month_calendar = calendar.monthcalendar(year, month)
    
    weeks_info = {
        'total_weeks': len(month_calendar),
        'weeks': [],
        'partial_weeks': 0,
        'full_weeks': 0
    }
    
    for i, week in enumerate(month_calendar):
        week_days = [day for day in week if day != 0]  # 0以外の日付
        is_partial = len(week_days) < 7
        
        week_info = {
            'week_number': i + 1,
            'days': week,
            'actual_days': week_days,
            'days_count': len(week_days),
            'is_partial': is_partial
        }
        
        weeks_info['weeks'].append(week_info)
        
        if is_partial:
            weeks_info['partial_weeks'] += 1
        else:
            weeks_info['full_weeks'] += 1
    
    return weeks_info

# 使用例
year = 2024
month = 2

weeks_count = get_weeks_in_month(year, month)
print(f"{year}年{month}月の週数: {weeks_count}週")

detailed_info = get_detailed_weeks_info(year, month)
print(f"完全週: {detailed_info['full_weeks']}週")
print(f"部分週: {detailed_info['partial_weeks']}週")

ISO週番号での週数計算

from datetime import date, timedelta

def get_iso_weeks_in_month(year, month):
    """ISO週番号を使用した月の週数計算"""
    # 月の最初と最後の日
    first_day = date(year, month, 1)
    if month == 12:
        last_day = date(year + 1, 1, 1) - timedelta(days=1)
    else:
        last_day = date(year, month + 1, 1) - timedelta(days=1)
    
    # ISO週番号を取得
    first_week = first_day.isocalendar()[1]
    last_week = last_day.isocalendar()[1]
    
    # 年をまたぐ場合の考慮
    if last_week < first_week:  # 12月末から1月初旬の場合
        weeks_in_year = date(year, 12, 28).isocalendar()[1]
        total_weeks = (weeks_in_year - first_week + 1) + last_week
    else:
        total_weeks = last_week - first_week + 1
    
    return {
        'total_iso_weeks': total_weeks,
        'first_iso_week': first_week,
        'last_iso_week': last_week,
        'first_day': first_day,
        'last_day': last_day
    }

# 使用例
iso_info = get_iso_weeks_in_month(2024, 1)
print(f"ISO週数情報: {iso_info}")

実用的な週計算関数

営業週の計算

import calendar
from datetime import date, timedelta

def get_business_weeks_info(year, month):
    """営業週の情報を取得"""
    month_calendar = calendar.monthcalendar(year, month)
    
    business_info = {
        'total_weeks': len(month_calendar),
        'business_days_per_week': [],
        'total_business_days': 0
    }
    
    for week in month_calendar:
        business_days = 0
        for day_num in week:
            if day_num != 0:  # 有効な日付
                day_date = date(year, month, day_num)
                if day_date.weekday() < 5:  # 月〜金
                    business_days += 1
        
        business_info['business_days_per_week'].append(business_days)
        business_info['total_business_days'] += business_days
    
    return business_info

# 使用例
business_info = get_business_weeks_info(2024, 1)
print(f"営業日情報: {business_info}")

週ごとの詳細分析

import calendar
from datetime import date

def analyze_month_by_weeks(year, month):
    """月を週ごとに詳細分析"""
    month_calendar = calendar.monthcalendar(year, month)
    weekday_names = ['月', '火', '水', '木', '金', '土', '日']
    
    analysis = {
        'month': f"{year}年{month}月",
        'total_weeks': len(month_calendar),
        'weeks_detail': []
    }
    
    for week_num, week in enumerate(month_calendar, 1):
        week_detail = {
            'week_number': week_num,
            'dates': [],
            'business_days': 0,
            'weekend_days': 0,
            'total_days': 0
        }
        
        for day_index, day in enumerate(week):
            if day != 0:
                day_date = date(year, month, day)
                weekday_name = weekday_names[day_index]
                
                day_info = {
                    'date': day,
                    'weekday': weekday_name,
                    'is_business_day': day_index < 5,
                    'is_weekend': day_index >= 5
                }
                
                week_detail['dates'].append(day_info)
                week_detail['total_days'] += 1
                
                if day_index < 5:
                    week_detail['business_days'] += 1
                else:
                    week_detail['weekend_days'] += 1
        
        analysis['weeks_detail'].append(week_detail)
    
    return analysis

# 使用例
analysis = analyze_month_by_weeks(2024, 1)
print(f"=== {analysis['month']} 週別分析 ===")
for week in analysis['weeks_detail']:
    print(f"第{week['week_number']}週: {week['total_days']}日 "
          f"(営業日: {week['business_days']}日, 週末: {week['weekend_days']}日)")

複数月の比較分析

年間の月別日数・週数比較

import calendar

def compare_months_in_year(year):
    """年間の月別日数・週数を比較"""
    month_names = ['', '1月', '2月', '3月', '4月', '5月', '6月',
                   '7月', '8月', '9月', '10月', '11月', '12月']
    
    comparison = {
        'year': year,
        'months': [],
        'total_days': 0,
        'total_weeks': 0
    }
    
    for month in range(1, 13):
        _, days = calendar.monthrange(year, month)
        weeks = len(calendar.monthcalendar(year, month))
        
        month_data = {
            'month': month,
            'month_name': month_names[month],
            'days': days,
            'weeks': weeks,
            'is_leap_year': calendar.isleap(year) and month == 2
        }
        
        comparison['months'].append(month_data)
        comparison['total_days'] += days
        comparison['total_weeks'] += weeks
    
    return comparison

# 使用例
year_comparison = compare_months_in_year(2024)
print(f"=== {year_comparison['year']}年 月別比較 ===")
print(f"年間総日数: {year_comparison['total_days']}日")
print(f"年間総週数: {year_comparison['total_weeks']}週")

print("\n月別詳細:")
for month_data in year_comparison['months']:
    leap_note = " (うるう年)" if month_data['is_leap_year'] else ""
    print(f"{month_data['month_name']}: {month_data['days']}日, {month_data['weeks']}週{leap_note}")

四半期ごとの集計

import calendar

def quarterly_analysis(year):
    """四半期ごとの日数・週数分析"""
    quarters = {
        'Q1': [1, 2, 3],
        'Q2': [4, 5, 6],
        'Q3': [7, 8, 9],
        'Q4': [10, 11, 12]
    }
    
    quarterly_data = {}
    
    for quarter, months in quarters.items():
        total_days = 0
        total_weeks = 0
        total_business_days = 0
        
        for month in months:
            _, days = calendar.monthrange(year, month)
            weeks = len(calendar.monthcalendar(year, month))
            
            # 営業日の計算
            business_days = 0
            month_calendar = calendar.monthcalendar(year, month)
            for week in month_calendar:
                for day_index, day in enumerate(week):
                    if day != 0 and day_index < 5:  # 月〜金
                        business_days += 1
            
            total_days += days
            total_weeks += weeks
            total_business_days += business_days
        
        quarterly_data[quarter] = {
            'total_days': total_days,
            'total_weeks': total_weeks,
            'business_days': total_business_days,
            'weekend_days': total_days - total_business_days
        }
    
    return quarterly_data

# 使用例
quarterly_data = quarterly_analysis(2024)
print("=== 2024年 四半期別分析 ===")
for quarter, data in quarterly_data.items():
    print(f"{quarter}: {data['total_days']}日, {data['total_weeks']}週 "
          f"(営業日: {data['business_days']}日)")

特殊な計算パターン

月の第N週の日数計算

import calendar

def get_nth_week_days(year, month, week_number):
    """月の第N週の日数を取得"""
    month_calendar = calendar.monthcalendar(year, month)
    
    if week_number > len(month_calendar) or week_number < 1:
        return None
    
    week = month_calendar[week_number - 1]
    actual_days = [day for day in week if day != 0]
    
    return {
        'week_number': week_number,
        'days': week,
        'actual_days': actual_days,
        'days_count': len(actual_days),
        'is_full_week': len(actual_days) == 7
    }

# 使用例
nth_week = get_nth_week_days(2024, 1, 1)
print(f"第1週の情報: {nth_week}")

月またぎ週の計算

import calendar
from datetime import date, timedelta

def get_cross_month_weeks(year, month):
    """月をまたぐ週の情報を取得"""
    # 当月のカレンダー
    current_month = calendar.monthcalendar(year, month)
    
    # 前月と次月の最後/最初の週を取得
    prev_month = month - 1 if month > 1 else 12
    prev_year = year if month > 1 else year - 1
    
    next_month = month + 1 if month < 12 else 1
    next_year = year if month < 12 else year + 1
    
    prev_month_cal = calendar.monthcalendar(prev_year, prev_month)
    next_month_cal = calendar.monthcalendar(next_year, next_month)
    
    result = {
        'first_week_incomplete': current_month[0][0] == 0,
        'last_week_incomplete': current_month[-1][6] == 0,
        'cross_month_weeks': []
    }
    
    # 最初の週が不完全な場合
    if result['first_week_incomplete']:
        prev_week_days = [day for day in prev_month_cal[-1] if day != 0]
        current_week_days = [day for day in current_month[0] if day != 0]
        
        result['cross_month_weeks'].append({
            'type': 'first_week',
            'prev_month_days': prev_week_days,
            'current_month_days': current_week_days,
            'total_days': len(prev_week_days) + len(current_week_days)
        })
    
    # 最後の週が不完全な場合
    if result['last_week_incomplete']:
        current_week_days = [day for day in current_month[-1] if day != 0]
        next_week_days = [day for day in next_month_cal[0] if day != 0]
        
        result['cross_month_weeks'].append({
            'type': 'last_week',
            'current_month_days': current_week_days,
            'next_month_days': next_week_days,
            'total_days': len(current_week_days) + len(next_week_days)
        })
    
    return result

# 使用例
cross_weeks = get_cross_month_weeks(2024, 1)
print(f"月またぎ週の情報: {cross_weeks}")

統計情報の生成

月の統計サマリー

import calendar
from datetime import date

def generate_month_statistics(year, month):
    """月の統計情報を生成"""
    _, days_in_month = calendar.monthrange(year, month)
    month_calendar = calendar.monthcalendar(year, month)
    
    # 曜日ごとの日数カウント
    weekday_counts = [0] * 7
    weekday_names = ['月', '火', '水', '木', '金', '土', '日']
    
    for week in month_calendar:
        for day_index, day in enumerate(week):
            if day != 0:
                weekday_counts[day_index] += 1
    
    # 統計情報の計算
    business_days = sum(weekday_counts[:5])  # 月〜金
    weekend_days = sum(weekday_counts[5:])   # 土日
    
    statistics = {
        'year': year,
        'month': month,
        'total_days': days_in_month,
        'total_weeks': len(month_calendar),
        'business_days': business_days,
        'weekend_days': weekend_days,
        'weekday_distribution': dict(zip(weekday_names, weekday_counts)),
        'is_leap_year': calendar.isleap(year),
        'month_efficiency': round(business_days / days_in_month * 100, 1)
    }
    
    return statistics

# 使用例と表示
stats = generate_month_statistics(2024, 1)
print(f"=== {stats['year']}年{stats['month']}月 統計情報 ===")
print(f"総日数: {stats['total_days']}日")
print(f"週数: {stats['total_weeks']}週")
print(f"営業日: {stats['business_days']}日")
print(f"週末: {stats['weekend_days']}日")
print(f"営業日効率: {stats['month_efficiency']}%")
print("\n曜日別分布:")
for weekday, count in stats['weekday_distribution'].items():
    print(f"  {weekday}曜日: {count}日")

まとめ

  • 日数取得calendar.monthrange()で月の日数を効率的に取得
  • 週数計算calendar.monthcalendar()で週単位の分析が可能
  • 営業日計算:曜日情報を活用した実用的な計算
  • 統計分析:月別、四半期別、年間の比較分析
  • 特殊パターン:月またぎ週、第N週、ISO週番号の考慮

これらの方法を活用することで、カレンダーベースの様々な計算処理が効率的に実装できます。

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座