ハッピーマンデー制度により、一部の日本の祝日は月日固定ではなく、曜日で固定して連休になるようにつくられています。
2012年12月現在、月曜日に移動した国民の祝日は以下の4つです
・成人の日(1月の第2月曜日) ・海の日(7月の第3月曜日) ・敬老の日(9月の第3月曜日) ・体育の日(10月の第2月曜日)
たとえば、成人の日は、1月の第2月曜日で、それが何日にあたるかはその年によって異なります。
PHP でこれを調べるには、ある曜日の第1週が何日かを計算し、何週目かによって 7 を足していきます。
<?php
//年
$year = 2038;
//名前, 月, 週, 曜日(0~6)の順
$holiday = array(
array("成人の日", 1, 2, 1),
array("海の日", 7, 3, 1),
array("敬老の日", 9, 3, 1),
array("体育の日", 10, 2, 1)
);
$datetime = new DateTime();
$datetime->setTimezone( new DateTimeZone('Asia/Tokyo') );
foreach($holiday as $value){
list($name, $month, $week, $wday) = $value;
//その月の始まりは何曜日か
$datetime->setDate($year, $month, 1);
$w = (int)$datetime->format('w');
//指定された曜日の最初の日
$first = ($wday - $w >= 0) ? 1 + $wday - $w : 1 + $wday - $w + 7;
//日にちを算出
$day = $first + ( 7 * ($week - 1) );
$datetime->setDate($year, $month, $day);
echo $name . ': ' . $datetime->format('Y-m-d') . "\n";
}
出力結果
成人の日: 2038-01-11 海の日: 2038-07-19 敬老の日: 2038-09-20 体育の日: 2038-10-11
$holiday には「名前, 月, 週, 曜日」の順で指定します。曜日は日曜日が 0 で土曜が 6 です。