2009/11/20

カレンダーを作る2

カレンダーを作る1で作ったphpを改造します。
追加する処理は、

  1. 年月の取得と日付を移動するリンクの準備
  2. 祝日の読み込み
  3. カレンダーを整形
  4. スタイルシートを修正

です。
サンプル

1.年月の取得と日付を移動するリンクの準備

前回の$yと$mをURLクエリがある場合URLクエリから取得します。
そのデータを元に必要なデータを作ります。
今回は2000年から2020年までのカレンダーとします。

if($_GET["y"]&&$_GET["m"]){
$y = $_GET["y"];
$m = $_GET["m"];
}else{
$y = date("Y",time());
$m = date("m",time());
}
$t = date("t",mktime(0,0,0,$m,1,$y));//月初めの曜日
$start = date("w",mktime(0,0,0,$m,1,$y));//月初めの曜日
$end = date("w",mktime(0,0,0,$m,$t,$y));//月末の曜日
$week = array("日","月","火","水","木","金","土");//曜日の表示
$y_start = 2000;//カレンダー開始年
$y_end = 2020;//カレンダー終了年

先月と来月へのリンクを準備します。

$_SERVER[“SCRIPT_NAME”]
現在のスクリプトのパス
//先月へのリンク
//カレンダー開始年以前の場合リンクしない
if(date("Y",mktime(0,0,0,$m-1,1,$y)) >= $y_start){
$bk = "<a href="\"".$_SERVER["SCRIPT_NAME"]."?y=".date("Y",mktime(0,0,0,$m-1,1,$y))."&m=".date("m",mktime(0,0,0,$m-1,1,$y))."\""><<</a>";//前月へのリンク
}else{
$bk = "<<";
}
//来月へのリンク
//カレンダー終了年を超えた場合リンクしない
if(date("Y",mktime(0,0,0,$m+1,1,$y)) <= $y_end){ $nx = "<a href="\"".$_SERVER["SCRIPT_NAME"]."?y=".date("Y",mktime(0,0,0,$m+1,1,$y))."&m=".date("m",mktime(0,0,0,$m+1,1,$y))."\"">>></a>";//来月へのリンク
}else{
$nx = ">>";
}

$bkに先月へのリンク、$nxに来月へのリンクが出来ました。

次にフォームでのリンクを準備します。

//フォームリンク
//年のフォーム
for($i=$y_start;$i<=$y_end;$i++){ $slctd=""; if($i==$y){$slctd=" selected=\"selected\"";} $set_y[]="".$i."";
}
//月のフォーム
for($i=1;$i<=12;$i++){ $i=str_pad($i,2,"0",STR_PAD_LEFT); $slctd=""; if($i==$m){$slctd=" selected=\"selected\"";} $set_m[]="".$i."";
}

$set_yと$set_mに年と月のデータが入りました。
このデータを使いフォームリンク部分を完成させます。

onchange=”this.form.submit()”
フォームに変更があった場合送信する
$form="

<form method="\"get\"" action="\"".$_SERVER["SCRIPT_NAME"]."\""><select name="\"y\"" onchange="\"this.form.submit()\"">".join($set_y,"\n")."</select>/
<select name="\"m\"" onchange="\"this.form.submit()\"">".join($set_m,"\n")."</select></form>";

リンク部分のパーツは完成です。

2.祝日の読み込み

今回はAddinBoxさんの祝日についてで公開されているXMLソースを利用させていただきます。
必要な年数(今回は2000年~2020年)のXMLデータを
HolidayList.xmlの名前で文字コードをUTF-8にして保存。
注意
保存の際<?xml version=”1.0″ encoding=”shift_jis”?>の部分を
<?xml version=”1.0″ encoding=”UTF-8″?>に変更する。
利用するデータの取得は

simplexml_load_file関数
XMLファイルをパースし、オブジェクトに代入する
get_object_vars関数
指定したオブジェクトのプロパティを取得する

を利用します。

$content=simplexml_load_file("HolidayList.xml");//XMLデータをオブジェクトに変換
foreach($content->Holiday->Row as $key=>$val){
$val= get_object_vars($val);
$hy = $val["Year"];//年
$hm = $val["Month"];//月
$hd = $val["Day"];//日
$hn = $val["Name1"];//祝日名
if($hy == $y && $hm == $m){//該当の月の場合
$hlist[$hd] = $hn;
}
}

$hlistに該当月の祝日データが入りました。

3.カレンダーを整形します。

前回と同様に日付を配列にしていきます。
前回から変更する処理は

  1. 日付を挿入時$hlist(祝日データ)に存在する日付を赤文字にする
  2. 祝日以外の日曜日を赤文字に土曜日を青文字にする

です。
曜日のチェックは

  1. 変数$jを0で初期化
  2. $iが7で割り切れるとき($j%7==0)日曜日
  3. $iを7で割って余りが6のとき($j%7==6)土曜日

となります。

$j=0;
$tbl="";
for($i=0;$i<$start;$i++){//1日までの空白 $tbl[]="-"; $j++; } for($i=1;$i<=$t;$i++){//日付 $val=$i; if($hlist && $hlist[$val]){//祝日のチェック $val="<span class="\"hol\"">".$val."</span>";
}else{
if($j%7==0){//日曜日のチェック
$val="<span class="\"sun\"">".$val."</span>";
}
if($j%7==6){//土曜日のチェック
$val="<span class="\"sat\"">".$val."</span>";
}
}
$tbl[]=$val;
$j++;
}
for($i=$end;$i<6;$i++){//月末からの空白 $tbl[]="-"; }

祝日は<span class=”hol”>日付</span> 日曜日は<span class=”sun”>日付</span> 土曜日は<span class=”sat”>日付</span> として$tblにデータをいれました。 ここまでで準備したデータを元にtableにしていきます。 theadに曜日、tfootに該当月の祝日、tbodyに日付をいれます。

 //リンクの書き出し $table="
<div class="\"ttl\"">".$bk.$form.$nx."</div>
\n";//年月の書き出し
$table.="

";

//曜日の書き出し
$table.="

";
foreach($week as $val){
$table.= "

\n";
}
$table.="

\n

\n";
//祝日の書き出し
$table.="

";
if($hlist){
foreach($hlist as $key=>$val){
$table.="

";
}
}else{
$table.="

";
}
$table.="

";

//日付の書き出し
$table.="

";
$i=0;
foreach($tbl as $val){
if($i%7==0){
$table.="

\n";
}
$table.="

\n";
$i++;
if($i%7==0){
$table.="

\n";
}
}
$table.="
<table>
<thead>
<tr>
<th>".$val."</th>
</tr>
</thead>
<tfoot>
<tr>
<th class="\"ttl\"" colspan="\"7\"">今月の祝日</th>
</tr>
<tr>
<th>".$key."日</th>
<td colspan="\"6\"">".$val."</td>
</tr>
<tr>
<td colspan="\"7\"">祝日はありません</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>".$val."</td>
</tr>
</tbody>
</table>
\n";

4.スタイルシートの修正

必要部分のスタイルを記入し2.cssで保存します。

#main{
width:350px;
}
table{
border: 1px solid #ccc;
width: 100%;
}
.ttl{
background: #999;
color: #fff;
border: 1px solid #ccc;
text-align:center;
height:1.5em;
line-height:1.5em;
}
th{
border: 1px solid #ccc;
background: #ccc;
color: #fff;
font-weight: normal;
padding: 2px;
}
td{
border: 1px solid #ccc;
vertical-align: top;
}
tbody td{
height:50px;
text-align: center;
width: 50px;
}
form{
display: inline;
}
.ttl a{
font-weight: bold;
color:#fff;
}
.sun,.hol{
color: #f00;
}
.sat{
color: #00f;
}

5.html部分を整形し完成

<div id="main"><!--?php echo $table; ?--></div>

全体のソース

<!--?php

//表示する年月の取得

if($_GET["y"]&&$_GET["m"]){
	$y = $_GET["y"];
	$m = $_GET["m"];
}else{
	$y = date("Y",time());
	$m = date("m",time());
}

$t     = date("t",mktime(0,0,0,$m,1,$y));//月初めの曜日
$start = date("w",mktime(0,0,0,$m,1,$y));//月初めの曜日
$end   = date("w",mktime(0,0,0,$m,$t,$y));//月末の曜日
$week  = array("日","月","火","水","木","金","土");//曜日の表示

$y_start = 2000;//カレンダー開始年
$y_end   = 2020;//カレンダー終了年

//リンクの整形

//先月へのリンク
//カレンダー開始年以前の場合リンクしない
if(date("Y",mktime(0,0,0,$m-1,1,$y)) -->= $y_start){
$bk = "<a href="\"".$_SERVER["SCRIPT_NAME"]."?y=".date("Y",mktime(0,0,0,$m-1,1,$y))."&m=".date("m",mktime(0,0,0,$m-1,1,$y))."\""><<</a>";//前月へのリンク
}else{
$bk = "<<";
}

//来月へのリンク
//カレンダー終了年を超えた場合リンクしない
if(date("Y",mktime(0,0,0,$m+1,1,$y)) <= $y_end){ $nx = "<a href="\"".$_SERVER["SCRIPT_NAME"]."?y=".date("Y",mktime(0,0,0,$m+1,1,$y))."&m=".date("m",mktime(0,0,0,$m+1,1,$y))."\"">>></a>";//来月へのリンク
}else{
$nx = ">>";
}

//フォームリンク

//年のフォーム
for($i=$y_start;$i<=$y_end;$i++){ $slctd=""; if($i==$y){$slctd=" selected=\"selected\"";} $set_y[]="".$i."";
}

//月のフォーム
for($i=1;$i<=12;$i++){ $i=str_pad($i,2,"0",STR_PAD_LEFT); $slctd=""; if($i==$m){$slctd=" selected=\"selected\"";} $set_m[]="".$i."";
}

$form="

<form method="\"get\"" action="\"".$_SERVER["PHP_SELF"]."\""><select name="\"y\"" onchange="\"this.form.submit()\"">".join($set_y,"\n")."</select>/
<select name="\"m\"" onchange="\"this.form.submit()\"">".join($set_m,"\n")."</select></form>";

//祝日の読み込み
//http://www.h3.dion.ne.jp/~sakatsu/holiday_topic.htm
$content=simplexml_load_file("HolidayList.xml");//XMLデータをオブジェクトに変換
//var_dump($content->Period->FirstYear);
foreach($content->Holiday->Row as $key=>$val){
$val= get_object_vars($val);
$hy = $val["Year"]; //年
$hm = $val["Month"]; //月
$hd = $val["Day"]; //日
$hn = $val["Name1"]; //祝日名
if($hy == $y && $hm == $m){ //該当の月の場合
$hlist[$hd] = $hn;
}
}

$j=0;
$tbl="";
for($i=0;$i<$start;$i++){//1日までの空白 $tbl[]="-"; $j++; } for($i=1;$i<=$t;$i++){//日付 $val=$i; if($hlist && $hlist[$val]){ $val="<span class="\"hol\"">".$val."</span>";
}else{
if($j%7==0){
$val="<span class="\"sun\"">".$val."</span>";
}
if($j%7==6){
$val="<span class="\"sat\"">".$val."</span>";
}
}
$tbl[]=$val;
$j++;
}

for($i=$end;$i<6;$i++){//月末からの空白 $tbl[]="-"; } //リンクの書き出し $table="
<div class="\"ttl\"">".$bk.$form.$nx."</div>
\n";//年月の書き出し
$table.="

";

//曜日の書き出し
$table.="

";
foreach($week as $val){
$table.= "

\n";
}
$table.="

\n

\n";
//祝日の書き出し
$table.="

";
if($hlist){
foreach($hlist as $key=>$val){
$table.="

";
}
}else{
$table.="

";
}
$table.="

";

//日付の書き出し
$table.="

";
$i=0;
foreach($tbl as $val){
if($i%7==0){
$table.="

\n";
}
$table.="

\n";
$i++;
if($i%7==0){
$table.="

\n";
}
}
$table.="
<table>
<thead>
<tr>
<th>".$val."</th>
</tr>
</thead>
<tfoot>
<tr>
<th class="\"ttl\"" colspan="\"7\"">今月の祝日</th>
</tr>
<tr>
<th>".$key."日</th>
<td colspan="\"6\"">".$val."</td>
</tr>
<tr>
<td colspan="\"7\"">祝日はありません</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>".$val."</td>
</tr>
</tbody>
</table>
\n";
?>
<div id="main"><!--?php echo $table; ?--></div>