PHP

カレンダーを作成する

  1. 最終更新日:
  2. 公開日:

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

この記事のポイント

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

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

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

カレンダーの表示例

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

PHP コード例

<?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 コード例

<?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コードが始まります。

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 コード例

<?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つ進めます。

PHP コード例

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

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

PHP コード例

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

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

CSSの記述

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

CSS コード例

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」に設定すると、その年のカレンダーがしっかり表示されます。

記事一覧