PHPプログラミング

最終更新日:
公開日:

レシピ

日付・時刻

カレンダーを作成する

時刻に関連した関数を使って、指定した「年」のカレンダーを作成する方法について解説します。

この記事のポイント

  • 1年分のカレンダーを表示する
  • strtotime関数、mktime関数、date関数の3種類の関数を使う
  • 閏年にも対応

目次

PHPでカレンダーを作成する

時刻関連の処理を行うstrtotime関数mktime関数date関数を使うと、手軽にカレンダーを作成することができます。

こちらのカレンダーを表示するコードは次のようになります。

コード例

<?php
//------------------------------
// カレンダーを作成する
//------------------------------

// カレンダーを表示する「年」を指定する
$year = 2019;

// 年始のタイムスタンプを取得
$timestamp = strtotime("{$year}-01-01 00:00:00");
$weekday = 0;
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>カレンダーを作成する</title>
<style>
main {
	display: flex;
	flex-wrap: wrap;
}

table {
	margin-right: 10px;
	margin-bottom: 20px;
	border: 1px solid #555;
}

table caption {
	padding: 7px 0;
	font-size: 86%;
	color: #fff;
	line-height: 1.0em;
	background: #555;
}
table th,
table td {
	padding: 0 5px;
	font-size: 86%;
	color: #222;
	text-align: center;
}
table td {
	text-align: right;
}
</style>
</head>
<body>
<main>
	<?php for( $i=1; $i<=12; $i++): ?>
	<table>
		<caption><?php echo $i; ?>月</caption>
		<thead>
			<tr>
				<th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th>
			</tr>
		</thead>
		<tbody>
			<?php
			// 開始日を取得
			$start_day_timestamp = mktime(0,0,0,$i,1,$year);
		
			// 末日を取得
			$end_day_timestamp = mktime(0,0,0,($i+1),0,$year);
			$end_day = date("d", $end_day_timestamp);
	
			for( $j=1; $j <= $end_day; $j++ ) {
				
				if( $j === 1 ) {
		
					echo '<tr>';
		
					$weekday = date("w", $start_day_timestamp);
					
					for( $k=0; $k<$weekday; $k++ ) {
						echo '<td></td>';
					} 
				}
		
				echo '<td>'.$j.'</td>';
				$weekday++;
		
				if( 6 < $weekday ) {
					echo '</tr><tr>';
					$weekday = 0;
				}
			}
			?>
		</tbody>
	</table>
	<?php endfor; ?>
</main>
</body>
</html>

PHPのコードだけでなくHTMLとCSSも含むため少し長くなりますが、順に解説をしていきます。
大まかな流れは下記の通りです。

  • 表示する「年」を設定
  • HTMLの開始
  • for文で「月」ごとにカレンダーを表示
  • CSSの記述

表示する「年」を設定

コード例

<?php
//------------------------------
// カレンダーを作成する
//------------------------------

// カレンダーを表示する「年」を指定する
$year = 2019;

// 年始のタイムスタンプを取得
$timestamp = strtotime("{$year}-01-01 00:00:00");
$weekday = 0;
?>

まず、最初に$yearへカレンダーを表示したい「年」を設定します。
コード例では「2019」とします。

続いて、strtotime関数で年始のタイムスタンプを取得しています。
このタイムスタンプがカレンダーの起点です。

その下の$weekdayは週の曜日を保持するための変数です。
PHPの処理では曜日について、日(0)、月(1)、火(2)、水(3)、木(4)、金(5)、土(6)と対応しているため、まずは「0」をセットします。

ここまででPHPの初期設定は完了です。

HTMLの開始

続いて、HTMLコードが始まります。

コード例

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>カレンダーを作成する</title>
<style>

// CSSを記述

</style>
</head>
<body>
<main>

// カレンダーを表示するコードを記述

</main>
</body>
</html>

HTMLは表示の「枠」になります。
今回は必要最低限のため非常にシンプルです。

for文で「月」ごとにカレンダーを表示

コードを上から順に読むとCSSの方が先に記述されていますが、body要素にカレンダーのHTMLがあってこそのCSSなのでカレンダー表示部分を先に解説します。

コード例

<?php for( $i=1; $i<=12; $i++): ?>
<table>
	<caption><?php echo $i; ?>月</caption>
	<thead>
		<tr>
			<th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th>
		</tr>
	</thead>
	<tbody>
		<?php
		// 開始日を取得
		$start_day_timestamp = mktime(0,0,0,$i,1,$year);
	
		// 末日を取得
		$end_day_timestamp = mktime(0,0,0,($i+1),0,$year);
		$end_day = date("d", $end_day_timestamp);

		for( $j=1; $j <= $end_day; $j++ ) {
			
			if( $j === 1 ) {
	
				echo '<tr>';
	
				$weekday = date("w", $start_day_timestamp);
				
				for( $k=0; $k<$weekday; $k++ ) {
					echo '<td></td>';
				} 
			}
	
			echo '<td>'.$j.'</td>';
			$weekday++;
	
			if( 6 < $weekday ) {
				echo '</tr><tr>';
				$weekday = 0;
			}
		}
		?>
	</tbody>
</table>
<?php endfor; ?>

外側の「<?php for( $i=1; $i<=12; $i++): ?>」〜「<?php endfor; ?>」は、12ヶ月分ということで12回ループするように設定します。

続くtable要素は、まず曜日だけを出力します。

<table>
	<caption><?php echo $i; ?>月</caption>
	<thead>
		<tr>
			<th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th>
		</tr>
	</thead>
	<tbody>

// カレンダー

	</tbody>
</table>

次に、月初めと末日のタイムスタンプをそれぞれ取得します。
この2つのタイムスタンプを使い、「2019年1月1日〜2019年1月31日の間をループする」という条件式を作成していきます。

<?php
// 開始日を取得
$start_day_timestamp = mktime(0,0,0,$i,1,$year);
	
// 末日を取得
$end_day_timestamp = mktime(0,0,0,($i+1),0,$year);
$end_day = date("d", $end_day_timestamp);

月初めはどの日付も「1日」なので計算は必要ありませんが、末日は月によって変動があるためmktime関数が活躍します。

この関数は「日」に「0」を指定すると、先月末の日付のタイムスタンプを取得することができます。
例えば、「2019年2月28日」のタイムスタンプを取得したい場合、「2019年3月0日」をmktime関数に指定します。

mktime(0,0,0,3,0,2019);

タイムスタンプ形式のままだと処理がしづらいため、次の行で「日」のみ取得して$end_dayに入れます。

$end_day = date("d", $end_day_timestamp);

これで、月初から月末までループする準備が整いました。
次のfor文で、1日〜月末($end_day)までループし、日にちを出力していきます。

for( $j=1; $j <= $end_day; $j++ ) {
	
// ここに日にちを出力する処理が入る
	
}

1日のみ、開始の曜日を計算する必要があるため一手間かかります。
次の処理で、1日の曜日まで空のtd要素を挿入していきます。

if( $j === 1 ) {

	echo '<tr>';

	$weekday = date("w", $start_day_timestamp);
	
	for( $k=0; $k<$weekday; $k++ ) {
		echo '<td></td>';
	} 
}

具体的には、$start_day_timestampに入っている月初のタイムスタンプを使ってdate関数から曜日を取得します。
そして、その曜日になるまでfor文で空のtd要素を並べています。
例えば1日が水曜日だった場合は、日曜〜火曜まで空のtd要素を挿入します。
反対に、1日が日曜だった場合は空要素が挿入されません。

続くコードでは、td要素でマークアップした日にちを出力します。
その後、$weekdayに入っている曜日も1つ進めます。

echo '<td>'.$j.'</td>';
$weekday++;

もし$weekdayの数値が7以上になった場合は、曜日が土曜まで進んだことになるため日曜の「0」をセットします。
その時点でテーブルの行も改行となるため、締めのtr要素と次の開始であるtr要素を出力します。

if( 6 < $weekday ) {
	echo '</tr><tr>';
	$weekday = 0;
}

以上が、カレンダーの出力部分になります。
最後に、出力したHTMLの表示を整えるためにCSSを記述します。

CSSの記述

CSSはstyle要素に記述します。

コード例

main {
	display: flex;
	flex-wrap: wrap;
}

table {
	margin-right: 10px;
	margin-bottom: 20px;
	border: 1px solid #555;
}

table caption {
	padding: 7px 0;
	font-size: 86%;
	color: #fff;
	line-height: 1.0em;
	background: #555;
}
table th,
table td {
	padding: 0 5px;
	font-size: 86%;
	color: #222;
	text-align: center;
}
table td {
	text-align: right;
}

以上がカレンダーを表示するコードになります。
このコードを実行すると、冒頭の画像のようなカレンダーが表示されます。
「年」を「2020」に設定すると、その年のカレンダーがしっかり表示されます。