Pythonで日付をISO週に変換する魔法のメソッド: datetime.date.isocalendar() の詳細解説
datetime.date.isocalendar() は、Python の datetime
モジュールで提供されるメソッドで、特定の日付が ISO 週において何番目の週、何曜日に当たるかを返すものです。ISO 週は、国際標準化機構 (ISO) で定義された、1 年を 52 週または 53 週に分割する方法です。このメソッドは、国際的な日付管理や分析を行う際に役立ちます。
メソッドの構成
datetime.date.isocalendar()
メソッドは、以下の 3 つの値をタプル形式で返します。
- 年 (year)
対象となる日付が属する年 - 週 (week)
ISO 週における週番号 (1 から 53 まで) - 曜日 (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}日目")
自作関数は、柔軟性とカスタマイズ性に優れています。しかし、ロジックの設計やテストが必要であり、メンテナンスが大変になるという欠点があります。