PHPで地図で指定した場所の週間カレンダーを表示

(1/1)
PHPで地図で指定した場所の天気予報を求める」でつくったプログラムをベースに、「PHPで祝日を求める」「PHPで二十四節気一覧を作成」「PHPで日出没・月出没・月齢を計算」「PHPで3ヶ月カレンダーを作る」「PHPで月の満ち欠けを描画」を加え、地図で指定した地点の週間カレンダーを表示するPHPプログラムをつくる。

(2023年3月18日)予報地点情報ファイルを更新
(2023年2月11日)予報地点情報ファイルを更新
(2023年1月15日)太陽、月の位置計算の精度向上,予報地点情報ファイルを更新

サンプル・プログラムの実行例

PHPで地図で指定した場所の週間カレンダーを表示
Googleマップ表示

目次

サンプル・プログラム

圧縮ファイルの内容
weeklyCalendar.phpサンプル・プログラム本体
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」などを参照。include_path が通ったディレクトリに配置すること。
pahooWeather.php気象情報に関わるクラス pahooWeather。
気象情報に関わるクラスの使い方は「PHPで天気予報を求める」を参照。include_path が通ったディレクトリに配置すること。
pahooCalendar.php暦計算クラス pahooCalendar。
暦計算クラスの使い方は「PHPで日出没・月出没・月齢・潮を計算」を参照。include_path が通ったディレクトリに配置すること。
pahooCache.phpキャッシュ処理に関わるクラス pahooCache。
キャッシュ処理に関わるクラスの使い方は「PHPで天気予報を求める」を参照。include_path が通ったディレクトリに配置すること。
jmaweatherspots.xml予報地点情報ファイル。「PHPで天気予報を求める」参照。
jmaWeatherInit.php予報地点情報ファイル作成プログラム。「PHPで天気予報を求める」参照。
weeklyCalendar.php 更新履歴
バージョン 更新日 内容
3.0.0 2022/05/28 太陽・月に関わる計算精度向上
2.9 2022/05/28 雑節を追加,2033年問題解決案を追加
2.81 2022/03/19 ヘルプの修正
2.8 2021/08/08 土用の入り,丑の日を追加
2.7 2021/04/10 キャッシュ・システム導入:pahooCacheクラス
pahooGeoCode.php 更新履歴
バージョン 更新日 内容
6.1.0 2022/12/30 ip2address()追加
6.0.4 2022/12/13 PHP8.2対応
6.03 2022/05/29 マップにプロットできる場所を999箇所に拡大
6.02 2022/03/19 drawLeaflet()で移動時の緯度・経度を拾わないbug-fix
6.01 2021/12/06 bug-fix
pahooWeather.php 更新履歴
バージョン 更新日 内容
5.4 2023/02/11 FILE_VERSION = 2.2 に更新
5.3 2022/03/10 気象庁防災情報XMLのhttps化に対応
5.2 2021/04/08 pahoo_simplexml_loadをpahooCache::simplexml_loadへ
5.1 2021/04/02 キャッシュ・システム導入:pahooCacheクラス
5.03 2021/03/24 当日~2日後の天気予報が違う都市になる不具合を修正
pahooCalendar.php 更新履歴
バージョン 更新日 内容
4.3.2 2023/02/11 getSolarTerm72() 表記改訂:水澤腹堅→水沢腹堅
4.3.1 2023/02/03 表記改訂:バクムーン→バックムーン,スタージャンムーン→スタージョンムーン,七十二候
4.3.0 2023/01/14 コメント表記などを見直した,tenshanichi()追加
4.2.0 2023/01/11 getTimeDifference(),setTimeDifference()追加
4.1.0 2023/01/09 太陽,月の位置計算の基準をUTCに変更した
pahooCache.php 更新履歴
バージョン 更新日 内容
1.1.1 2023/02/11 コメント追記
1.1 2021/04/08 simplexml_load()メソッド追加
1.0 2021/04/02 初版

準備:pahooGeoCode クラス

  37: class pahooGeoCode {
  38:     var $items;     //検索結果格納用
  39:     var $error;     //エラー・フラグ
  40:     var $errmsg;    //エラー・メッセージ
  41:     var $hits;      //検索ヒット件数
  42:     var $webapi;    //直前に呼び出したWebAPI URL
  43: 
  44:     //Google Cloud Platform APIキー
  45:     //https://cloud.google.com/maps-platform/
  46:     //※Google Maps APIを利用しないのなら登録不要
  47:     var $GOOGLE_API_KEY_1 = '**************************';   //HTTPリファラ用
  48:     var $GOOGLE_API_KEY_2 = '**************************';   //IP制限用
  49: 
  50:     //Yahoo! JAPAN Webサービス アプリケーションID
  51:     //https://e.developer.yahoo.co.jp/register
  52:     //※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  53:     var $YAHOO_APPLICATION_ID = '*****************************';

地図サービスを利用するために、クラスファイル "pahooGeoCode.php" を使用する。組み込み関数  require_once  を使って読めるディレクトリに配置する。ディレクトリは、設定ファイル php.ini に記述されているオプション設定 include_path に設定しておく。
クラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

地図や住所検索として Google を利用するのであれば、Google Cloud Platform APIキー が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば、Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、それぞれ参照されたい。

準備:地図サービスの選択

  48: //地図描画サービスの選択
  49: //    0:Google
  50: //    2:地理院地図・OSM
  51: define('MAPSERVICE', 2);
  52: 
  53: //住所検索サービスの選択
  54: //    0:Google
  55: //    1:Yahoo!JAPAN
  56: //   11:HeartRails Geo API
  57: //   12:OSM Nominatim Search API
  58: define('GEOSERVICE', 1);
  59: 
  60: //逆ジオコーディングサービスの選択
  61: //    0:Google
  62: //    1:Yahoo!JAPAN
  63: //   11:HeartRails Geo API
  64: //   21:簡易ジオコーディングサービス
  65: define('REVGEOSERVICE', 21);

表示する地図は、Googleマップ地理院地図・オープンストリートマップ(OSM)から選べる。あらかじめ、定数 MAPSERVIC に値を設定すること。
住所検索サービスは、GoogleYahoo!JAPANHeartRails Geo APIOSM Nominatim Search API から選べる。あらかじめ、定数 GEOSERVICE に値を設定すること。
逆ジオコーディングサービスは、GoogleYahoo!JAPANHeartRails Geo API簡易ジオコーディングサービスから選べる。あらかじめ、定数 REVGEOSERVICE に値を設定すること。
PHPで地図で指定した場所の天気予報を求める
地理院地図表示
PHPで地図で指定した場所の天気予報を求める
オープンストリートマップ表示

準備:キャッシュ・システム

  83: //キャッシュ保持時間(分) 0:キャッシュしない
  84: //気象庁へのアクセス負荷軽減のため,60分以上のキャッシュ保持をお勧めします.
  85: define('LIFE_CACHE', 120);
  86: 
  87: //キャッシュ・ディレクトリ
  88: //書き込み可能で,外部からアクセスされないディレクトリを指定してください.
  89: //最大150Mバイトを消費します.天気予報系プログラムは同じディレクトリで構わない.
  90: define('DIR_CACHE', './pcache/');

気象庁サイトへ負荷をかけないよう、キャッシュ・クラス pahooCache を導入した。使用方法については、「PHPで天気予報を求める - キャッシュ・システム」を参照いただきたい。
キャッシュ保持時間、キャッシュ・ディレクトリともに、自サイトの環境に応じて変更してほしい。天気予報系プログラム(「PHPで天気予報を求める」「PHPで地図で指定した場所の天気予報を求める」「PHPで地図で指定した場所の週間カレンダーを表示」)は全て同じディレクトリを指定することで、気象庁サイトへのアクセス回数がさらに減少する。

解説:カレンダー作成

 290: /**
 291:  * カレンダー情報を追加する
 292:  * @param   object $pcl   pahooCalendarオブジェクト
 293:  * @param   array  $spot  場所情報
 294:  * @param   array  $items カレンダー情報配列
 295:  * @return  なし
 296: */
 297: function addWeeklyCalendar($pcl, $spot, &$items) {
 298:     //雑節テーブル
 299:     $table_za = array('春社', '秋社', '八十八夜', '入梅', '二百十日', '二百二十日');
 300: 
 301:     $longitude = $spot['longitude'];
 302:     $latitude  = $spot['latitude'];
 303:     $height    = $spot['height'];
 304:     $year  = date('Y');
 305:     $month = 0;
 306:     $yy = ($items[0]['month'<2? $year - 1 : $year;
 307: 
 308:     //彼岸
 309:     $higan = $pcl->getHigan($year);
 310:     //雑節
 311:     $zassetsu = $pcl->getZassetsu($year);
 312:     ////旧暦計算用テーブル準備
 313:     $pcl->makeLunarCalendar($yy, RESOLVE2033);
 314: 
 315:     foreach ($items as $i=>$item) {
 316:         if (is_numeric($i)) {
 317:             //翌年
 318:             if ($month > $items[$i]['month']) {
 319:                 $year++;
 320:                 $month = $items[$i]['month'];
 321:                 //彼岸
 322:                 $higan = $pcl->getHigan($year);
 323:                 //雑節
 324:                 $zassetsu = $pcl->getZassetsu($year);
 325:             } else if ($month < $items[$i]['month']) {
 326:                 $month = $items[$i]['month'];
 327:             }
 328:             $day = $items[$i]['day'];
 329:             $items[$i]['year'] = $year;
 330: 
 331:             //日出没・月出没・月齢・距離
 332:             $sunrise = $pcl->sun_time(0, $longitude, $latitude, $height, $year, $month, $day);
 333:             $items[$i]['sunrise'] = $pcl->day2hhmm($sunrise);
 334:             $sunset = $pcl->sun_time(1, $longitude, $latitude, $height, $year, $month, $day);
 335:             $items[$i]['sunset'] = $pcl->day2hhmm($sunset);
 336:             $moonrise = $pcl->moon_time(0, $longitude, $latitude, $height, $year, $month, $day);
 337:             $items[$i]['moonrise'] = ($moonrise == FALSE? '---' : $pcl->day2hhmm($moonrise);
 338:             $moonset = $pcl->moon_time(1, $longitude, $latitude, $height, $year, $month, $day);
 339:             $items[$i]['moonset'] = ($moonset == FALSE? '---' : $pcl->day2hhmm($moonset);
 340:             $items[$i]['moonage'] = $pcl->moon_age($year, $month, $day, CALC_HOUR, 0, 0);
 341:             $items[$i]['moondist'] = sprintf('%4.3f', $pcl->distance_moon($year, $month, $day, CALC_HOUR, 0, 0));
 342: 
 343:             //潮
 344:             $moonmeridian = $pcl->moon_time(2, $longitude, $latitude, $height, $year, $month, $day);
 345:             $moonmeridian = ($moonmeridian == FALSE? '---' : $pcl->day2hhmm($moonmeridian);
 346:             $items[$i]['tide'] = (preg_match('/([0-9]+)\:([0-9]+)/', $moonmeridian, $arr> 0? $pcl->tide($year, $month, $day, $arr[1], $arr[2], 0)  : '';
 347: 
 348:             //二十四節気
 349:             $items[$i]['solarterm24'] = $pcl->getSolarTerm($year, $month, $day);
 350: 
 351:             //七十二候
 352:             $items[$i]['solarterm72'] = $pcl->getSolarTerm72($year, $month, $day);
 353: 
 354:             //土用
 355:             list($ss1, $ss2) = $pcl->isDoyo($year, $month, $day);
 356:             if ($ss2 == '明け') {
 357:                 $ss2 = '';
 358:             } else if (($ss1 !'夏'&& ($ss2 == '丑')) {
 359:                 $ss2 = '';
 360:             }
 361:             if ($ss1 !'' && $ss2 !'') {
 362:                 $ss2 = '土用の' . $ss2;
 363:             }
 364:             $items[$i]['doyo'] = $ss2;
 365: 
 366:             //彼岸
 367:             if (($higan[0]['in']['month'] == $month&& ($higan[0]['in']['day'] == $day)) {
 368:                 $solarterm = '彼岸入り';
 369:                 $ss2 = '彼岸入り' . $ss2;
 370:             } else if (($higan[0]['out']['month'] == $month&& ($higan[0]['out']['day'] == $day)) {
 371:                 $solarterm = '彼岸明け';
 372:                 $ss2 = '彼岸明け' . $ss2;
 373:             } else if (($higan[1]['in']['month'] == $month&& ($higan[1]['in']['day'] == $day)) {
 374:                 $solarterm = '彼岸入り';
 375:                 $ss2 = '彼岸入り' . $ss2;
 376:             } else if (($higan[1]['out']['month'] == $month&& ($higan[1]['out']['day'] == $day)) {
 377:                 $solarterm = '彼岸明け';
 378:                 $ss2 = '彼岸明け' . $ss2;
 379:             }
 380:             //雑節
 381:             foreach ($table_za as $label) {
 382:                 if (($zassetsu[$label]['month'] == $month&& ($zassetsu[$label]['day'] == $day)) {
 383:                     $solarterm = $label;
 384:                     $ss2 = $label . $ss2;
 385:                 }
 386:             }
 387: 
 388:             //祝日
 389:             $holiday = $pcl->getHoliday($year, $month, $day, 'jp');
 390:             $items[$i]['holiday'] = ($holiday == FALSE? '' : $holiday;
 391: 
 392:             //旧暦
 393:             list($oldmonth, $oldday, $oldleap) = $pcl->Gregorian2Lunar($year, $month, $day);
 394:             $oldleap = $oldleap ? '閏' : '';
 395:             $items[$i]['oldcal'] = sprintf('%s%d月%d日', $oldleap, $oldmonth, $oldday);
 396:             $items[$i]['rokuyou'] = $pcl->rokuyou($oldmonth, $oldday);
 397: 
 398:             //日の干支
 399:             $items[$i]['eto'] = $pcl->eto_day($year, $month, $day);
 400:         }
 401:     }
 402: }

ユーザー関数 addWeeklyCalendar は、天気予報によって取得した年月日に基づき、カレンダーの計算を行う。
具体的には、毎日の天気予報情報を格納した配列 $items に対して、日出没・月出没・月齢、二十四節気、七十二候、土用、祝日、旧暦の順にデータを追加していく。

グレゴリオ暦から旧暦を求める手順は、「PHPで3ヶ月カレンダーを作る」で紹介している。

解説:表示とURLパラメータ

 586: //パラメータ
 587: $id        = (int)getParam('id',          FALSE, 0);            //表示モード
 588: $query     = (string)getParam('query',    TRUE,  '');           //地図検索キー
 589: $latitude  = (float)getParam('latitude',  FALSE, DEF_LATITUDE); //緯度
 590: $longitude = (float)getParam('longitude', FALSE, DEF_LONGITUDE);    //経度
 591: $zoom      = (int)getParam('zoom',        FALSE, DEF_ZOOM);     //ズーム
 592: $type      = (string)getParam('type',     FALSE, DEF_TYPE);     //マップタイプ
 593: $category  = (string)getParam('category', FALSE, 'address');    //カテゴリ
 594: $outenc    = (string)getParam('charset',  FALSE, INTERNAL_ENCODING);

URLパラメータを使って
weeklyCalendar?id=1&query=%E6%9C%AD%E5%B9%8C%E5%B8%82
のようにすることで、query をキーワードにして検索した地点のカレンダーのみを表示させることができる。つまり、このスクリプトをホームページやブログの一部として組み込むことで、週間天気予報を表示するパーツになる。
query はUTF-8をURLエンコードしたもの。Yahoo!JAPAN住所検索を使う場合は、category をあわせて指定すること。
また、出力はHTML文のみとなり、スタイルシートは本体ページの方で用意していただきたい。必要なclassは次の通り。

 136: <style>
 137: /* カレンダー:キャプション */
 138: h3.caption {
 139:     width: {$width}px;
 140:     font-size: 140%;
 141:     text-align: center;
 142: }
 143: /* カレンダー */
 144: table.DailyCalendar {
 145:     table-layout: fixed;
 146:     width: {$width}px;
 147:     border: solid 1px gray;
 148:     border-collapse: collapse;
 149:     margin-top:10px;
 150: }
 151: /* カレンダー:日付表示 */
 152: td.label1 {
 153:     border:solid 1px gray;
 154:     border-collapse: collapse;
 155:     padding: 4px;
 156:     white-space: nowrap;
 157:     font-size: 120%;
 158:     text-align:center;
 159:     color: white;
 160:     background-color: dimgray;
 161: }
 162: /* カレンダー:旧暦表示 */
 163: span.oldcal {
 164:     font-size: 80%;
 165: }
 166: /* カレンダー:ラベル表示 */
 167: td.label3 {
 168:     width: {$width3}px;
 169:     border:solid 1px gray;
 170:     border-collapse: collapse;
 171:     padding: 4px;
 172:     white-space: nowrap;
 173:     font-size: 100%;
 174:     text-align: center;
 175:     background-color: gainsboro;
 176: }
 177: /* カレンダー:データ表示 */
 178: td.data3 {
 179:     width: {$width3}px;
 180:     border:solid 1px gray;
 181:     border-collapse: collapse;
 182:     padding: 4px;
 183:     white-space: nowrap;
 184:     font-size: 100%;
 185:     text-align: center;
 186: }
 187: /* カレンダー:データ表示(小さい文字) */
 188: td.data4 {
 189:     width: {$width3}px;
 190:     border:solid 1px gray;
 191:     border-collapse: collapse;
 192:     padding: 4px;
 193:     white-space: nowrap;
 194:     font-size: 70%;
 195:     text-align: center;
 196: }
 197: /* 月の満ち欠け画像 */
 198: img.moonage {
 199:     width:  {$width9}px;
 200:     height: {$width9}px;
 201:     padding: 5px;
 202: }
 203: /* 天気予報表:予報アイコン */
 204: img.wicon {
 205:     width: 60px;
 206: }
 207: </style>

また、親となるホームページやブログの文字コードセットにあわせ、charset 変数で出力文字コードを変更できるようにした。たとえば
weeklyCalendar?id=1&query=%E6%9C%AD%E5%B9%8C%E5%B8%82&charset=SJIS
とすると、シフトJISで出力することができる。
緯度・経度を直接、URLパラメータに渡すこともできる。
weeklyCalendar?id=1&latitude=26.591&longitude=127.977
のようにすることで、北緯26.591度、東経127.977度のカレンダーのみを表示させることができる。

参考サイト

(この項おわり)
header