Pythonで日付をISO週に変換する魔法のメソッド: datetime.date.isocalendar() の詳細解説


datetime.date.isocalendar() は、Python の datetime モジュールで提供されるメソッドで、特定の日付が ISO 週において何番目の週、何曜日に当たるかを返すものです。ISO 週は、国際標準化機構 (ISO) で定義された、1 年を 52 週または 53 週に分割する方法です。このメソッドは、国際的な日付管理や分析を行う際に役立ちます。

メソッドの構成

datetime.date.isocalendar() メソッドは、以下の 3 つの値をタプル形式で返します。

  1. 年 (year)
    対象となる日付が属する年
  2. 週 (week)
    ISO 週における週番号 (1 から 53 まで)
  3. 曜日 (weekday)
    1 (月曜日) から 7 (日曜日) まで

メソッドの例

from datetime import date

# 特定の日付を指定
dt = date(2024, 7, 15)  # 2024年7月15日

# isocalendar() メソッドを実行
result = dt.isocalendar()

# 結果の表示
print(f"ISO週: {result[0]}週, {result[1]}日目 ({result[2]}曜日)")

この例では、2024年7月15日について isocalendar() メソッドを実行し、以下の出力を得ます。

ISO週: 29週, 3日目 (月曜日)

つまり、2024年7月15日は、2024年の 29 週目の月曜日であることがわかります。

  • 経理処理における週ごとの売上集計を行う
  • 国際的な会議やイベントの日程を管理する
  • 特定の週に属する日付範囲を取得する
  • 12 月末を含む週は、翌年の 1 週目として扱われる場合と、その年の 53 週目として扱われる場合があります。これは、その年の 1 月 1 日が木曜日であるかどうかによって異なります。
  • ISO 週は、1 年のうち最初の木曜日を含む週を 1 週目とします。


例 1: 特定の週に属する日付範囲を取得する

from datetime import date


def get_week_range(year, week_num):
    """指定された年と週番号における日付範囲を取得します。

    Args:
        year (int): 対象となる年
        week_num (int): 対象となる週番号

    Returns:
        tuple: 開始日と終了日のタプル
    """
    start_date = date(year, 1, 1) + relativedelta.relativedelta(weeks=(week_num - 1))
    end_date = start_date + relativedelta.relativedelta(days=6)
    return start_date, end_date


# 特定の年と週番号を指定
target_year = 2024
target_week_num = 32

# 特定の週における日付範囲を取得
start_date, end_date = get_week_range(target_year, target_week_num)

# 結果の表示
print(f"第{target_week_num}週: {start_date}{end_date}")

このコードでは、get_week_range() 関数を使用して、指定された年と週番号における日付範囲を取得します。そして、取得した日付範囲を print() 関数で表示します。

例 2: 国際的な会議の日程を管理する

from datetime import date


def get_conference_dates(year, conference_week):
    """国際会議の日程を取得します。

    Args:
        year (int): 対象となる年
        conference_week (tuple): 会議開催週を (月, 週) のタプルで指定

    Returns:
        list: 会議開催日のリスト
    """
    start_date = date(year, 1, 1) + relativedelta.relativedelta(weekday=relativedelta.MO(1), weeks=(conference_week[1] - 1))
    conference_dates = []
    for i in range(conference_week[0]):
        conference_dates.append(start_date + relativedelta.relativedelta(days=i * 7))
    return conference_dates


# 会議開催年と開催週を指定
conference_year = 2025
conference_week = (2, 3)  # 2 週目の月曜日から開始

# 会議開催日のリストを取得
conference_dates = get_conference_dates(conference_year, conference_week)

# 結果の表示
for date in conference_dates:
    print(f"会議日: {date.isocalendar()}")

このコードでは、get_conference_dates() 関数を使用して、国際会議の日程を取得します。会議開催年と開催週を (月, 週) のタプルで指定し、会議開催日のリストを返します。そして、取得した会議開催日のリストを print() 関数で表示します。

from datetime import date


def get_weekly_sales(sales_data, start_date, end_date):
    """週ごとの売上を集計します。

    Args:
        sales_data (list): 売上データ (日付, 金額) のリスト
        start_date (date): 集計対象期間の開始日
        end_date (date): 集計対象期間の終了日

    Returns:
        dict: 週ごとの売上情報の辞書
    """
    weekly_sales = {}
    for date, amount in sales_data:
        if start_date <= date <= end_date:
            week_num = date.isocalendar()[1]
            if week_num not in weekly_sales:
                weekly_sales[week_num] = 0
            weekly_sales[week_num] += amount
    return weekly_sales


# 売上データ (架空)
sales_data = [
    (date(2024, 7, 8), 1000),
    (date(2024, 7, 9), 1500),
    (date(2024, 7, 10), 2200),
    (date(2024, 7,


手動計算

最も基本的な代替方法は、手動で計算することです。以下の式を使用して、ISO 週番号と曜日を計算できます。

def iso_calendar(dt):
    """指定された日付の ISO 週番号と曜日を計算します。

    Args:
        dt (date): 対象となる日付

    Returns:
        tuple: (ISO 週番号, 曜日)
    """
    year = dt.year
    start_date = date(year, 1, 1)
    days_since_year_start = dt - start_date
    day_of_year = days_since_year_start.days + 1
    week_num = (day_of_year - 1) // 7 + 1
    if week_num == 1 and dt.weekday() == 4:
        week_num = 52
        year -= 1
    day_of_week = dt.weekday() + 1
    return week_num, day_of_week

# 例
dt = date(2024, 7, 15)
week_num, day_of_week = iso_calendar(dt)
print(f"ISO週: {week_num}週, {day_of_week}日目")

この方法は、シンプルな構造で理解しやすいという利点があります。しかし、複雑なロジックが必要となる場合や、コードが冗長になりやすいという欠点もあります。

pandas ライブラリ

pandas ライブラリを使用すると、dt.isocalendar() メソッドと同様の機能を利用できます。

import pandas as pd

# 例
dt = pd.to_datetime('2024-07-15')
week_num, day_of_week = dt.isocalendar()
print(f"ISO週: {week_num}週, {day_of_week}日目")

pandas ライブラリは、データ分析やデータ処理に特化した機能が豊富に用意されています。そのため、データフレーム形式で日付データを扱っている場合は、この方法が適しています。一方、pandas ライブラリを導入する必要があり、コードが多少複雑になるという欠点があります。

dateutil ライブラリ

dateutil ライブラリは、日付と時間の処理に特化した機能を提供しており、relativedelta モジュールを使用して、柔軟な日付操作を行うことができます。

from dateutil.relativedelta import relativedelta

# 例
dt = date(2024, 7, 15)
start_date = date(dt.year, 1, 1)
week_num = (dt - start_date + relativedelta.relativedelta(weekday=relativedelta.MO(1))).days // 7 + 1
day_of_week = dt.weekday() + 1
print(f"ISO週: {week_num}週, {day_of_week}日目")

dateutil ライブラリは、複雑な日付操作や、カレンダー関連の処理を行う場合に適しています。しかし、ライブラリの導入が必要であり、コードが多少複雑になるという欠点があります。

自作関数

def my_isocalendar(dt):
    """独自のロジックで ISO 週番号と曜日を計算します。

    Args:
        dt (date): 対象となる日付

    Returns:
        tuple: (ISO 週番号, 曜日)
    """
    # 独自のロジックを実装

# 例
dt = date(2024, 7, 15)
week_num, day_of_week = my_isocalendar(dt)
print(f"ISO週: {week_num}週, {day_of_week}日目")

自作関数は、柔軟性とカスタマイズ性に優れています。しかし、ロジックの設計やテストが必要であり、メンテナンスが大変になるという欠点があります。