導入
Webアプリケーション開発において、カレンダー機能や期限計算、定期実行処理など、日付を扱うロジックは避けて通れません。特に「閏年(うるうどし)」の判定は、2月29日という特異な日付があるためにバグを引き起こしやすいポイントです。
自前で「4で割れるか」「100で割れるか」といった条件分岐を書くことも可能ですが、PHPには標準でこの判定を安全かつ簡潔に行うための機能が用意されています。今回は、現場で役立つ正しい閏年判定の実装手法を解説します。
基礎知識
閏年は「西暦が4で割り切れる年は閏年。ただし、100で割り切れる年は平年。ただし、400で割り切れる年は閏年」という複雑なルールがあります。
PHPで日付を扱う際、古くからある `date()` や `mktime()` といった関数を使う方法と、PHP 5.2以降で導入された強力な `DateTime` クラスを使う方法があります。実務では、拡張性が高く直感的な `DateTime` クラスを使用するのが現在の標準的なベストプラクティスです。
実装/解決策
最も推奨されるのは `DateTime` オブジェクトの `format(‘L’)` を使う方法です。
`L` フォーマット文字は、指定された年が閏年であれば「1」、平年であれば「0」を返します。この挙動は `date()` 関数でも同様ですが、`DateTime` クラスを使うことでタイムゾーンの考慮や日付の加算・減算といった他の操作とシームレスに連携できる利点があります。
サンプルプログラム
以下に、実務でそのまま利用できる判定処理のサンプルコードを提示します。
/
function isLeapYear(int $year): bool {
// DateTimeクラスをインスタンス化(1月1日を指定)
$date = new DateTime(“$year-01-01”);
// format(‘L’)は閏年であれば1、平年であれば0を返します
// bool型にキャストして返却します
return (bool)$date->format(‘L’);
}
// 実行例
$targetYear = 2024;
if (isLeapYear($targetYear)) {
echo “{$targetYear}年は閏年です。” . PHP_EOL;
} else {
echo “{$targetYear}年は平年です。” . PHP_EOL;
}
?>
応用・注意点
1. 厳密な型チェック: `date(‘L’)` や `DateTime::format(‘L’)` は文字列の「1」または「0」を返します。if文で直接判定する場合は `if ($date->format(‘L’) === ‘1’)` と記述すると、より厳密で安全なコードになります。
2. DateTimeImmutableの活用: 複雑な日付計算を行う場合は、破壊的変更(オブジェクト自体が書き換わること)を防ぐため、`DateTime` ではなく `DateTimeImmutable` クラスの使用を推奨します。これにより、予期せぬ副作用を防ぐことができます。
3. 誤ったロジックの回避: 自前で `if ($year % 4 === 0 && ($year % 100 !== 0 || $year % 400 === 0))` といったロジックを書くことは可能ですが、可読性が低く、将来的な修正コストも高くなります。可能な限りPHPの標準機能である `format(‘L’)` に任せるのが、バグを減らすための鉄則です。