PHPでその月の最初の月曜日を取得するときの注意点

PHPで日時処理を行うDateTimeクラスやDateTimeImmutableクラスのmodify()メソッドでは相対的な書式と呼ばれる記述が可能。これが意外と便利。 例えば、3日後の日付を取得しようとした場合、次のような記述が可能。

$now = new DateTimeImmutable();
$threeDaysLater = $now->modify("+3 day");

来月の1日だと次のようになる。

$nextMonth = $now->modify("first day of next month");

で、この方法を利用して、その月の最初の月曜日の日付を取得しようとして次のような記述をすると、思わぬバグに遭遇してしまう。

$aprilfool = new DateTimeImmutable("2020-04-01");
$firstMonday = $aprilfool->modify("first Monday");

このコードだと、 $firstMonday は2020/4/6を表し、確かに2020年4月の最初の月曜日となる。しかし、同じコードを2020年6月に適用すると問題となる。

$junefool = new DateTimeImmutable("2020-06-01");
$firstMonday = $junefool->modify("first Monday");

このコードを実行すると、なんと、 $firstMonday は2020/6/8になってしまう。2020年6月の最初の月曜日は6/1その日なのだ。つまり、 first Monday はその変数の日時から見て「最初の月曜日」という意味で、その月の最初の月曜日ではない。 「その月の最初の月曜日」を表したい場合は、次のように of this month をつける必要がある。

$junefool = new DateTimeImmutable("2020-06-01");
$firstMonday = $junefool->modify("first Monday of this month");