前回の記事の続き。
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/
