高校物理160203 views
高校国語788336 views
高校化学2924392 views
雑学1473612 views
高校日本史190571 views
小学社会310485 views
英語613639 views
小学算数1200427 views
りんご209490 views
高校生物551766 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

Python で「来月の第2月曜日」など N 番目の曜日を取得する

「毎月第2月曜日に会議」「第3金曜日がリリース日」といったスケジュールは、カレンダーアプリや業務システムでよく見かけます。Python で N 番目の曜日を計算する方法を解説します。

考え方

「第2月曜日」を求めるには、まず月初から最初の月曜日を見つけ、そこから7日を足せば2番目の月曜日になります。一般化すると、N 番目の曜日は「最初のその曜日 + 7 × (N - 1) 日」で計算できます。

基本の実装

特定の月の N 番目の曜日を取得する関数を作ってみましょう。

from datetime import date, timedelta

def nth_weekday(year, month, weekday, n):
    """
    指定した月の N 番目の曜日を取得
    weekday: 0=月, 1=火, 2=水, 3=木, 4=金, 5=土, 6=日
    n: 何番目か(1〜5)
    """
    # 月初
    first = date(year, month, 1)
    
    # 月初から最初のその曜日までの日数
    days_until = (weekday - first.weekday()) % 7
    first_weekday = first + timedelta(days=days_until)
    
    # N 番目なので (N-1) 週分足す
    result = first_weekday + timedelta(weeks=n - 1)
    
    # 月をまたいでいたら None を返す
    if result.month != month:
        return None
    
    return result

# 2025年1月の第2月曜日
print(nth_weekday(2025, 1, 0, 2))  # 2025-01-13

# 2025年1月の第3金曜日
print(nth_weekday(2025, 1, 4, 3))  # 2025-01-17

(weekday - first.weekday()) % 7 の部分がポイントです。月初の曜日と目的の曜日の差を計算し、負の値にならないように 7 で剰余を取っています。

曜日を文字列で指定する

曜日を数字で指定するのは分かりにくいので、文字列で指定できるようにしてみます。

from datetime import date, timedelta

WEEKDAYS = {
    "月": 0, "火": 1, "水": 2, "木": 3, "金": 4, "土": 5, "日": 6,
    "mon": 0, "tue": 1, "wed": 2, "thu": 3, "fri": 4, "sat": 5, "sun": 6,
}

def nth_weekday(year, month, weekday, n):
    if isinstance(weekday, str):
        weekday = WEEKDAYS[weekday.lower()]
    
    first = date(year, month, 1)
    days_until = (weekday - first.weekday()) % 7
    first_weekday = first + timedelta(days=days_until)
    result = first_weekday + timedelta(weeks=n - 1)
    
    if result.month != month:
        return None
    return result

print(nth_weekday(2025, 1, "月", 2))  # 2025-01-13
print(nth_weekday(2025, 1, "fri", 3))  # 2025-01-17

祝日の例:成人の日

成人の日は「1月の第2月曜日」と定められています。

def seijin_no_hi(year):
    """成人の日を取得"""
    return nth_weekday(year, 1, 0, 2)

for year in range(2025, 2030):
    print(f"{year}年: {seijin_no_hi(year)}")

出力:

# 2025年: 2025-01-13
# 2026年: 2026-01-12
# 2027年: 2027-01-11
# 2028年: 2028-01-10
# 2029年: 2029-01-08

月末から数える

「最終金曜日」のように月末から数えたい場合は、別のアプローチが必要です。

from datetime import date, timedelta
import calendar

def last_weekday(year, month, weekday):
    """指定した月の最後のその曜日を取得"""
    # 月末日を取得
    last_day = calendar.monthrange(year, month)[1]
    last = date(year, month, last_day)
    
    # 月末から遡って最初のその曜日
    days_back = (last.weekday() - weekday) % 7
    return last - timedelta(days=days_back)

# 2025年1月の最終金曜日
print(last_weekday(2025, 1, 4))  # 2025-01-31

プレミアムフライデーの計算などに使えますね。

calendar モジュールを使う方法

calendar モジュールにも同様の機能があります。

import calendar

# 2025年1月のカレンダーを行列で取得
cal = calendar.monthcalendar(2025, 1)

# 第2月曜日(各行の [0] が月曜日)
second_monday = [week[0] for week in cal if week[0] != 0][1]
print(second_monday)  # 13

ただし日付だけが返るため、date オブジェクトが欲しい場合は自前の関数のほうが使いやすいでしょう。