takeuchi
Google Calender iCal形式のデータから、日本の祝日リストを自動生成する
前回の記事の続き。
jQuery ui Datepickerに祝日を反映する
祝日を反映したのはいいけど、祝日リストを直書きするのは大変だなということで、
こんな方法はどうでしょうか。
はじめに
まずどこかに都合のいい日本の祝日APIみたいやつないかなぁ。というところから始まり、
以下のようなイメージを持ちました。
- 祝日データを探す…
- それをなんとか取得し、都合の良い配列に整形する
- JSONファイルにする
- キャッシュする
Google Calenderを活用する
お世話になりっぱなしのGoogleに日本の祝日データを提供していただくことにしました。
なんとiCal形式であれば取得できるので、PHPのfile_get_contentsを使って取得し、なんとかします。
<?php /** * JSON 生成 * @param $ical_url */ function creat_holiday_json($ical_url) { $dates = []; // iCal データの取得 $ics = file_get_contents($ical_url); if (empty($ics)) { return false; } // イベントごとに区切って配列化 $events = explode('END:VEVENT', str_replace("\r", '', $ics)); // 日付を求める foreach ($events as $i => $event) { if (preg_match('/DTSTART;\D*(\d+)/m', $event, $date) != 1) { continue; } $datetime = strtotime($date[1]); $dates[$i] = date('Ymd', $datetime); } // 日付 昇順にソートして返却 sort($dates); file_put_contents('holiday.json', json_encode($dates, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); } $ical_url = 'https://calendar.google.com/calendar/ical/japanese__ja@holiday.calendar.google.com/public/full.ics'; creat_holiday_json($ical_url);
これでJSONファイル生成ができました!
JSONファイルをキャッシュさせる
ただページにアクセスされる度に、毎回この処理が行われるのは非効率なので、
JSONファイルを生成した時間が、ある一定期間経過していたら処理されるしたい。
そこで、PHPのfilemtime関数で、JSONファイルの最終更新日を確認するようにしました。
<?php /** * JSON 生成 * @param $ical_url * @return array|false */ function get_date_from_ics($ical_url) { $dates = []; // iCal データの取得 $ics = file_get_contents($ical_url); if (empty($ics)) { return false; } // イベントごとに区切って配列化 $events = explode('END:VEVENT', str_replace("\r", '', $ics)); // 日付を求める foreach ($events as $i => $event) { if (preg_match('/DTSTART;\D*(\d+)/m', $event, $date) != 1) { continue; } $datetime = strtotime($date[1]); $dates[$i] = date('Ymd', $datetime); } // 日付 昇順にソートして返却 sort($dates); return $dates; } /** * jsonファイルの最終更新日を見て、毎月更新される。 * @param $file_path * @param $ical_url */ function holiday_json_write($file_path, $ical_url) { // 現在日時を取得 $now_time = date('Ym'); $file_time = ''; // 最終更新日の取得 if(file_exists($file_path)){ $file_timestamp = filemtime($file_path); $file_time = date('Ym', $file_timestamp); } // 年月の文字列で比較して、月一更新されるようにする $time = $file_time - $now_time; if($time < 0) { $holidays = get_date_from_ics($ical_url); file_put_contents($file_path, json_encode($holidays, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); } } $file_path = 'holiday.json'; $ical_url = 'https://calendar.google.com/calendar/ical/japanese__ja@holiday.calendar.google.com/public/full.ics'; holiday_json_write($file_path, $ical_url);
※こちらの例では、今日から数えて1ヶ月以上古かったら更新されるようになります。
これでようやく問題解決です!
生成したJSONファイルにアクセスする
あとは、こちらのjsonファイルをJSで$.ajaxもしくは、$.getJSONで処理してあげれば
.complete()以降は同じです。
<script> var holidays = []; $.getJSON('holiday.json' , function(json) { var value; Object.keys(json).forEach(function(key) { value = this[key]; holidays.push(value); }, json); }).complete(function(){ $('#datepicker').datepicker({ dayNamesMin: ['SUN','MON','TUE','WED','THU','FRI','SAT'], beforeShowDay: function(date) { var disable; var editedDate = date.getFullYear() + ('0' + (date.getMonth() + 1)).slice(-2) + ('0' + date.getDate()).slice(-2); for (var i = 0; i < holidays.length; i++) { disable = holidays[i]; if (editedDate == disable) return [true, 'ui-datepicker-week-end']; } return [true, '']; } }); }); </script>
カレンダーUIが必要で、祝日反映する機会は結構あるかなぁと思うので
何かの参考になれば幸いです。
【参考】
・option-beforeShowDay
http://api.jqueryui.com/datepicker/#option-beforeShowDay
・getjson
http://api.jquery.com/jquery.getjson/