【PHP実践|実務向け】PHPでハッピーマンデー制度の祝日を動的に算出する方法

導入

実務において、カレンダー機能やイベントスケジュールの作成、あるいは勤怠管理システムなどで「特定の月の第n曜日」を求めるケースは頻繁に発生します。特に日本の「ハッピーマンデー制度」のように、日付が固定されず毎年変動する祝日を扱う場合、ロジックで動的に算出する必要があります。本稿では、PHPのDateTimeクラスを活用して、スマートかつ正確に特定の日付を取得する方法を解説します。

基礎知識

PHPで日付計算を行う際、最も推奨されるのはDateTimeクラスを使用することです。かつてのdate()関数やmktime()関数を用いる手法に比べ、タイムゾーンの考慮や日付の加算・減算が容易かつ安全に行えるためです。
今回の実装では、以下のロジックを用います。
1. 対象月の1日が何曜日であるかを取得する。
2. 1日から目標の曜日までの差分を計算し、その月の「第1週の該当曜日」を特定する。
3. 求めたい週数に応じて、7日間を乗算した日数を加算する。

実装/解決策

特定の曜日がその月の第何週目かを求めるには、基準となる「第1週の曜日」を特定するのが鍵です。
月の1日の曜日と、目標とする曜日(例:月曜日)の差分をとることで、その月で最も早い目標曜日の日付が算出できます。あとは、(求める週数 – 1) 7日を足すだけで、正確な日付が導き出せます。

サンプルプログラム

以下のコードは、ハッピーマンデー制度の祝日を計算する実用的なスニペットです。

  • 指定した年、月、第n週、曜日から日付を算出する
  • 曜日: 0(日) ~ 6(土)
  • /
    function getSpecificDay($year, $month, $week, $wday) {
    $date = new DateTime();
    $date->setTimezone(new DateTimeZone(‘Asia/Tokyo’));

    // 対象月の1日にセット
    $date->setDate($year, $month, 1);

    // 1日の曜日を取得 (0:日, 1:月… 6:土)
    $firstDayOfWeek = (int)$date->format(‘w’);

    // その月の「第1週」における目標曜日の日付を算出
    // 差分がマイナスになる場合は、翌週が第1週となる
    $first = ($wday – $firstDayOfWeek >= 0) ? 1 + ($wday – $firstDayOfWeek) : 1 + ($wday – $firstDayOfWeek) + 7;

    // 求めたい週数分だけ7日を加算
    $day = $first + (7 ($week – 1));

    $date->setDate($year, $month, $day);
    return $date->format(‘Y-m-d’);
    }

    // 使用例:2024年の成人の日(1月の第2月曜日)を取得
    echo “成人の日: ” . getSpecificDay(2024, 1, 2, 1) . PHP_EOL;
    ?>

    応用・注意点

    現場で実装する際に特に注意すべきポイントが2つあります。

    1. タイムゾーンの設定
    サーバーの環境によってデフォルトのタイムゾーンが異なる場合があります。必ずsetTimezone(new DateTimeZone(‘Asia/Tokyo’))を明示的に呼び出し、意図しない日付のズレを防いでください。

    2. 月の範囲外への加算
    今回のロジックは単純な算術計算です。もし「第5週」などを計算する際、その月の日数(28〜31日)を超えてしまう場合は注意が必要です。DateTimeクラスのsetDateは自動的に日付を繰り越しますが、それが「翌月になっていないか」をチェックするロジック(例:$resultDate->format(‘m’) が元の月と一致するか)を組み込むと、より堅牢なプログラムになります。

    これらの日付計算は、祝日テーブルをDBで管理する場合の「自動生成バッチ」などにも応用可能です。ぜひ活用してください。

    タイトルとURLをコピーしました