【PHP】期間内の祝日・定休日などを含んだ日付情報を取得する


1.まず最初に、開始日と終了日で指定した期間内の日付リストを「Y-m-d」形式の配列で取得する関数を用意します。

/**
 * 期間内の日付(Y-m-d 形式)を取得する
 *
 * @param       string      $date_start     開始日(Y-m-d)
 * @param       string      $date_end       終了日(Y-m-d)
 * @return      array                       日付の配列
 */
function getDateList($date_start, $date_end) {

    $DateTime = new DateTime($date_start);

    $date_list = array();

    while ($DateTime->format('Y-m-d') <= $date_end){ $date_list[] = $DateTime->format('Y-m-d');

        $DateTime->add(new DateInterval('P1D'));        // 1日加算
    }

    return $date_list;
}

 

2.次に、開始日と終了日で指定した期間内の日付情報を配列で取得する関数を用意します。

先程の関数と、Google Calendar API を合わせることで、期間内の定休日・祝日情報などを取得することが可能になります。

/**
 * 期間内の日付情報を取得
 *
 * @param       string      $date_start     開始日(Y-m-d)
 * @param       string      $date_end       終了日(Y-m-d)
 * @param       array       $option         オプション
 *                array       holiday         定休日の曜日番号(0:日曜 ... 6:土曜)
 * @return      array                       日付の配列
 */
function getDateInfo($date_start, $date_end, $option = array()) {

    $date_list = getDateList($date_start, $date_end);
    $holiday_list = getHolidayList($date_start, $date_end);

    $date_info = array();

    foreach ($date_list as $d_val) {

        $DateTime = new DateTime($d_val);

        $date = $DateTime->format('Y-m-d');
        $w = $DateTime->format('w');

        if (isset($option['holiday']) && in_array($w, $option['holiday'])) {
            $date_info[$date]['holiday'] = 1;

        } elseif (in_array($d_val, $holiday_list)) {
            $date_info[$date]['holiday'] = 1;

        } else {
            $date_info[$date]['holiday'] = 0;
        }
    }

    return $date_info;
}

 

3.「getHolidayList 関数」を用意します。
詳細は、以下の記事に載っています。
【PHP】Google Calendar API を使用して、日本の祝日を取得する方法

 

4.関数を呼び出します。

$option = array(
    'holiday' => array(
        0,        // 日曜
        6,        // 土曜
    ),
);

$date_list = getDateInfo('2017-11-01', '2017-12-31', $option);

option に休日を設定できます。
上記の例では「土」「日」が休日の場合の指定方法です。

戻り値について。
休日の場合は「holiday」が「1」
平日の場合は「holiday」が「0」
で返ってきます。

ちなみに「option」と「返り値」に「holiday」を付けて配列の階層を深くしているのは、「曜日」を返せるようにしたりなどの拡張を見越してです。


【PHP】Google Calendar API を使用して、日本の祝日を取得する方法


Google Calendar API を使用して祝日を取得する方法について。

Google 側の仕様が結構変わっているようで、ネット上に落ちてる情報が古かったので載せておきます。

(今回紹介する Google Calendar API の利用例は、コチラの記事にて 【PHP】期間内の祝日・定休日などを含んだ日付情報を取得する

1.API キーの発行

Google Cloud Platformにアクセスして「Google API を利用する」を選択する。

他者にAPIキーを利用されないように「HTTP リファラー」などで、APIキーに制限をかける。

「HTTP リファラー」で、APIキーに制限をかけた場合、同一ドメイン内であれば、Google Map などにも使いまわせます。

2.Google Calendar API を使用して祝日を取得する関数を用意

/**
 * 期間内の祝日を取得する
 *
 * @param       string      $date_start         開始日(Y-m-d)
 * @param       string      $date_end           終了日(Y-m-d)
 * @param       string      $google_api_key     Google API Key
 * @return      array                           祝日の配列
 */
function getHolidayList($date_start, $date_end, $google_api_key) {

    // カレンダーID
    $calendar_id = urlencode('ja.japanese#holiday@group.v.calendar.google.com');

    $max_results = 100;

    $startDate = new DateTime($date_start);
    $endDate = new DateTime($date_end);

    $param_start = $startDate->format('Y-m-d') . 'T00:00:00Z';
    $param_end = $endDate->format('Y-m-d') . 'T00:00:00Z';

    $url  = 'https://www.googleapis.com/calendar/v3/calendars/' . $calendar_id . '/events';
    $url .= '?key=' . $google_api_key;
    $url .= '&timeMin=' . $param_start;
    $url .= '&timeMax=' . $param_end;
    $url .= '&maxResults=' . $max_results;
    $url .= '&orderBy=startTime';
    $url .= '&singleEvents=true';

    $ref = 'http://humo-life.net';

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_REFERER, $ref);

    $result = curl_exec($ch);

    curl_close($ch);

    if (empty($result) === true) {
        return array();
    }

    $json = json_decode($result);

    if (empty($json->items) === true) {
        return array();
    }

    $holiday_list = array();

    foreach ($json->items as $item) {
        $holiday_list[] = $item->start->date;
    }

    return $holiday_list;
}

ざっくり解説

カレンダーIDは、Googleカレンダーの設定画面から確認可能です。
https://calendar.google.com/calendar/r

API に制限をかけたので「CURLOPT_REFERER」でリファラーを設定する必要があります。

3.実際に使ってみる

使用例は以下の記事にて。
「2」で紹介している「getDateInfo」関数内で使用しています。
【PHP】期間内の祝日・定休日などを含んだ日付情報を取得する


フォームの入力内容をAjaxで加工後、別タブに送信(Ajaxとsubmitの2回送信)


フォームで入力された内容を、別タブで確認させたいが、単にsubmitで送信するのではなく、一度プログラムを通して加工する必要がある、という面倒な案件があったので、メモとして残しておきます。

javascript

function sample(url){

  // フォームの入力内容を取得し、クエリ文字列に変換
  var form = $('#form_id');
  var query_str = form.serialize();

  var postData = {
    'query_str' : query_str,
  };

  $.ajax({
    async: false,       // ajax を同期処理にする
    url: './act.php',   // 送信先ファイル名
    type : 'POST',
    data : postData,
    timeout: 10000,

  }).done(function(getData){
    // 前回追加したフォームを削除
    var old = document.getElementById('append_data');
    if (old) {
      document.form_id.removeChild(old);
    }

    // ajaxで取得したデータをフォームに追加
    var appendData = document.createElement('input');
    appendData.type = 'hidden';
    appendData.id = 'append_data';
    appendData.name = 'append_data';
    appendData.value = getData;

    document.form_id.appendChild(appendData);
  });

  // 指定 URL に submit
  document.form_id.action = url;
  document.form_id.enctype = 'application/x-www-form-urlencoded';
  document.form_id.target = '_blank';
  document.form_id.submit();
}

 

処理内容は、以下の流れになってます。

1.フォームにデータを入力する
 

2.ボタンを押された際に「sample」関数を呼び出す

<input type="button" value="確認" onclick="sample('http://hoge.hoge/disp.html');">

 

3.フォームの入力内容を「serialize()」を使い、クエリ形式で取得

// クエリ形式
category=1&title=sample

 

4.act.php に ajax でPOST送信

act.php の例

// クエリ文字列の取得例
$input_data = '';

if (isset($_POST['query_str'])) {
    $query_str = $_POST['query_str'];

    // クエリ文字列として送られてきたフォームの値を、input_data に格納する
    parse_str($query_str, $input_data);

	// こんな感じで取得できる
    // $input_data['category'] = 1;
    // $input_data['title'] = 'sample';
}

// 適当に加工

// 出力例
// 配列などにも対応させるため、シリアル化している
echo serialize($output_data);

 

5.act.php の出力内容をフォームにhiddenで追加する
2回め以降は、前回追加したフォームデータが残っているので、まずは削除してから追加しています。
 

6.別タブに submit
action の URL を書き換えているので、必要であれば書き換え前のURLを保存し、書き戻してください。
同様に、enctype や target も。
 

7.submit されたデータを受け取って表示
PHP での受け取り例

// POSTデータの取得
$post_data = $_POST;

// 追加データの取得
$append_data = array();
if (isset($_POST['append_data'])) {
    $append_data = unserialize($_POST['append_data']);
}

// POSTデータに、追加データをセット
if (is_array($append_data)) {
    foreach ($append_data as $key => $val) {
        if (isset($val)) {
            if (isset($post_data[$key])) {
                $post_data[$key] += $val;
            } else {
                $post_data[$key] = $val;
            }
        }
    }
}

 

最初は ajax 完了後に submit したいということで ajaxの「always」で行けないか?と試したのですが、何故か「always」の中に「document.form_id.submit();」を書くと動きませんでした。
そこで、仕方なく ajax を「async: false」で同期処理にしています。

それなら「submit()」を辞めればいいんじゃないか?とも思いましたが、テキストエリアの入力に使っている CKEditor が、エディタの入力内容を textarea の value にセットするタイミングが submit の時だったようで、これを submit 以外の時にも対応させるのは時間が掛かりそうなため断念しました。

この辺は改良すれば、もっとスマートに行けそうです。