PHP で祝日列挙
友人より**祝日の情報をネットから取得したいが良い方法はないか?**という質問があり、私も興味があったので調べてみた。ググって初めにみつけたものは以下の質問。
色々なサービスはあるけれど省庁の運用する公的なものは見当たらない。次にカレンダー系のサービスをあたってみたところ Google Calendar API がよさそうな感じ。
この API を使用した PHP サンプルは Zend Framework の Zend Gdata を用いたものが大半である。PHP 的にはこのフレームワークに乗るのが一般的なのだろう。
しかし今回は PHP の勉強によさそうなので、直接 API を利用するスクリプトを書いてみる事にした。Eclipse PDT とデバッガ使用の練習にもなる。
はじめに
今回作成したスクリプトは、WordPress のプラグインとして動作するようにした。
このスクリプトをプラグインとして登録してから記事にショートコードを書くと、単純な ul
- li
のリストとして祝日の年月日と名前 (昔は日本語だったそうだが今は英語になっている) が記事に埋め込まれる。
[HOLIDAY year="2009" month="10" limit="100"]
実装
実装は以下のようになる。XAMPP で動作確認済み。仕様についてはソース中にコメントとして記述した。
<?php
/*
Plugin Name: WP Holiday
Plugin URI:
Description: Google Calndar API で祝日を取得します。
Version: 0.1
Author: アカベコ
Author URI: https://akabeko.me/
*/
/**
* 指定された年、月の祝日リストを取得します。
*
* @param[in] $atts ショートコードの引数。year 省略時は今年、month 省略時は当月、limit 省略時は 100 件として扱います。
* @return HTML 形式の祝日情報文字列。
*/
function getHoliday( $atts ) {
extract( shortcode_atts(array('year' => '', 'month' => '', 'limit' => '' ), $atts ) );
$dateBegin = "";
$dateEnd = "";
$query = makeQuery( $year, $month, $limit, $dateBegin, $dateEnd );
if ( $query == "" ) {
return "<p><strong>WP-Holiday Error</strong> : 年と月の指定に問題があります。</p>";
}
$feed = "http://www.google.com/calendar/feeds/japanese@holiday.calendar.google.com/public/full" . "?" . $query;
$xml = simplexml_load_file( $feed );
if ( !$xml ) {
return "<p><strong>WP-Holiday Error</strong> : XML の読み込みに失敗しました。</p>";
}
$ret = "<p>" . $dateBegin . " ~ " . $dateEnd . "の祝日</p>" . enumHoliday( $xml );
return $ret;
}
/**
* 祝日情報を列挙します。
*
* @param $xml カレンダー情報を読み込んだ XML オブジェクト。
* @return HTML 形式の祝日情報文字列。
*/
function enumHoliday($xml) {
$ret = "\n<ul>\n";
foreach ( $xml->entry as $entry ) {
$gd = $entry->children("http://schemas.google.com/g/2005");
$attributes = $gd->when->attributes();
// $gd->when[ 'startTime' ] だと何故か null が返るので、属性を検索する
foreach ( $attributes as $name => $value) {
if ( $name == "startTime" ) {
$ret .= "<li>" . $value . " : " . $entry->title . "</li>\n";
break;
}
}
}
$ret .= "</ul>\n";
return $ret;
}
/**
* 指定された年、月から Google Calendar API 用クエリを生成します。
*
* @param[in] $year 年。省略時は、今年として扱います。
* @param[in] $month 月。省略時は、当月として扱います。
* @param[in] $limit 最大取得数。省略時は 100 件として扱います。
* @param[out] $dateBegin 祝日列挙の開始日。
* @param[out] $dateEnd 祝日列挙の終了日。
* @return 成功時はクエリ文字列。失敗時は空文字。
*/
function makeQuery( $year, $month, $limit, &$dateBegin, &$dateEnd ) {
// 開始・終了の範囲設定
if ( $year == "" ) {
$dateBegin = date( "Y-m-01" );
$dateEnd = date( "Y-m-t" );
} else if ( $month == "" ) {
if ( !checkdate( 1, 1, $year ) ) {
return "";
}
$dateBegin = date( "Y-01-01", mktime( 0, 0, 0, 1, 1, $year ) );
$dateEnd = date( "Y-12-t", mktime( 0, 0, 0, 12, 1, $year ) );
} else {
if ( !checkdate( $month, 1, $year ) ) {
return "";
}
$dateBegin = date( "Y-m-01", mktime( 0, 0, 0, $month, 1, $year ) );
$dateEnd = date( "Y-m-t", mktime( 0, 0, 0, $month, 1, $year ) );
}
return "start-min=" . $dateBegin . "&start-max=" . $dateEnd . "&max-results=" . ( is_numeric( $limit ) ? $limit : "100" );
}
add_shortcode( 'HOLIDAY', 'getHoliday' );
?>
出力例は以下。月まで指定すると出力数が少ないため year だけ 2009 を指定して、2009 年の全祝日を出してみた。
<p>2009-01-01 ~ 2009-12-31の祝日</p>
<ul>
<li>2009-12-23 : The Emperor's Birthday</li>
<li>2009-04-29 : Showa Day</li>
<li>2009-09-21 : Respect for the Aged Day</li>
<li>2009-01-01 : New Year's Day</li>
<li>2009-02-11 : National Foundation Day</li>
<li>2009-07-20 : Marine Day</li>
<li>2009-11-23 : Labour Thanksgiving Day</li>
<li>2009-10-12 : Health and Sports Day</li>
<li>2009-05-04 : Greenery Day</li>
<li>2009-11-03 : Culture Day</li>
<li>2009-05-03 : Constitution Memorial Day</li>
<li>2009-01-12 : Coming-of-Age Day</li>
<li>2009-05-05 : Children's Day</li>
</ul>
課題
今回のスクリプトは最低限の機能しかないので、課題が色々とある。機会があれば修正するかもしれないので、ぱっと思いついたものをメモっておく。
- データが取得されたままの順番で出力されている
- ソートすべきだろう
- 呼び出しの度にデータ取得が行われる
- 祝日の更新頻度は低いはず
- 更新がなければキャッシュを表示したい
- 出力状態が貧弱
- AmazonLink のようなテンプレ機能が欲しい
- 管理画面がない
- テンプレ機能とか入れたら必要になるだろう