#028
posted on 2021.02.09

Google Calendar APIのAPIキーとカレンダーIDでGoogleカレンダーのJSONデータを取得。

Google Calendar APIのAPIキーを利用して、カレンダーIDで指定したGoogleカレンダーのJSONデータをPHPで取得する方法のメモ。

※ 「APIキー」と「カレンダーID」の取得方法は前の記事を参照。

※ この方法は、データを取得するGoogleカレンダーの「Access permissions」がpublicになっている必要がある。

 

Google Calendar APIの公式リファレンス

 

 

カレンダーのJSONデータ取得のURLを作成

Google Calendar APIの「APIキー」と、データを取得したいGoogleカレンダーの「カレンダーID」が事前に必要。

 

「APIキー」と「カレンダーID」を使用して、カレンダーのJSONデータ取得のHTTPリクエストをするURLを作成する作業。

※ HTTPリクエストでクエリ設定できるパラメーターに関する公式リファレンス

  • singleEvents : 公式リファレンスでは「繰り返し設定の予定の、繰り返された分をインスタンス(実体)にし、(繰り返し設定の無い)単一の予定と、繰り返しのインスタンスだけを返し、元の予定を返さないかどうか」という説明になっているが、自分の試した限りでは「false」にすると何の予定も取得できなくなったので「true」を設定。デフォルトは「false」。
  • orderBy : 「取得する予定データの並び順」。「startTime」(予定開始日時順)か「updated」(最終更新日時順)を指定できる。デフォルトは「an unspecified, stable order.」となっているが、自分の試した限りでは「updated」で動作していると思われる。(「startTime」を指定する場合は、「singleEvents」は「true」にする。)
  • maxResults : 「取得する予定データの最大件数」。デフォルトは「250」件。ページ当たりの最大は「2500」件。
  • timeMin : 「取得する予定データの日時(終了時間)の下限の値」。デフォルトは「指定無し」(フィルタリングしない)。「RFC3339」形式のタイムスタンプで指定する必要がある。ミリ秒は無視される。
  • timeMax : 「取得する予定データの日時(開始時間)の上限の値」。デフォルトは「指定無し」(フィルタリングしない)。「RFC3339」形式のタイムスタンプで指定する必要がある。ミリ秒は無視される。
  • timeZone : 「取得する予定データに適用するタイムゾーン設定」。デフォルトは「カレンダー側で設定されているタイムゾーン」。

※ 「RFC3339」は「ISO 8601」とほぼ同じIETFによる規格のようなので、日時はPHPのdate()関数で「ISO 8601」形式のタイムスタンプに変換して指定する。

※ 下記では、「現在時刻」〜「2年後」までで登録されている予定を「50件」取得。

//APIキー
$api_key = '取得したAPIキー';
//カレンダーID
$calendar_id = 'ja.japanese#holiday@group.v.calendar.google.com';//「日本の祝日」のID

//カレンダーIDをURLにエンコード
$calendar_id = urlencode($calendar_id);
//googleカレンダーAPIのURL
$gcalendar_api_url = 'https://www.googleapis.com/calendar/v3/calendars/'.$calendar_id.'/events?';

//データ取得の開始日と終了日を指定
//UTCと日本の時差9時間
$jp_offset = 9*60*60; //9時間(32400秒)
//現在の日時を取得
if(date_default_timezone_get() == 'Asia/Tokyo'){
//PHPのデフォルトタイムゾーンが日本の場合
  $today = date('Y-m-d H:i:s');
}else{
//デフォルトタイムゾーンが日本以外の場合
  //現在の日時を日本時間に補正
  $today = gmdate('Y-m-d H:i:s', (mktime(date('H'),date('i'),date('s'),date('n'), date('j'),date('Y')))+$jp_offset);
}
//カレンダーから取得するデータの最後の日時を指定
$end_date = date('Y-m-d H:i:s', strtotime("$today +2 year"));//現在から2年後
//フォーマット'c'でタイムスタンプをISO 8601形式に変換
$q_start = date('c', strtotime($today));
$q_end = date('c', strtotime($end_date));
//予定イベントの取得件数
$q_num = 50;

//APIに送信するクエリを作成
$query = [
  'key' => $api_key,
  'singleEvents' => 'true',//デフォルトはfalse
  'orderBy' => 'startTime',//'startTime'予定開始日時か'updated'最終更新日時
  'maxResults' => $q_num,//デフォルトは250、最大2500
  'timeMin' => $q_start,//デフォルトは指定無し
  'timeMax' => $q_end,//デフォルトは指定無し
  'timeZone' => 'Asia/Tokyo'//デフォルトはカレンダー側での設定のタイムゾーン
];
//APIに送信するURLにクエリを付加
$gcalendar_api_url = $gcalendar_api_url.http_build_query($query);

date(‘フォーマット’) : デフォルトタイムゾーンでの現在時刻を指定フォーマットで返す。

mktime(時, 分, 秒, 月, 日, 年) : 指定した日時のUNIXタイムスタンプを返す。

gmdate(‘フォーマット’, ‘タイムスタンプ’) : 指定したタイムスタンプをGMT(グリニッジ標準時)の時刻にして指定フォーマットで返す。

strtotime(‘英文形式日付’) : 日付をUnixタイムスタンプに変換して返す。

http_build_query(‘配列’) : 配列からURLにエンコードされたクエリ文字列を生成。

 

 

カレンダーのJSONデータを取得

上述で作成したURLでGoogle Calendar APIにアクセスしてJSONデータを取得し、データを整形してHTMLに出力する作業。

  1. PHPのcURL()関数を使ってGoogle Calendar APIにアクセスしてJSONデータを取得。(cURLが使えないサーバーの場合は、file_get_contents()関数を使う。)
  2. 取得したデータを整形し、連想配列にしてオブジェクトを変数に格納。
  3. HTMLコードにしてデータを出力。

※ 取得できるカレンダーイベントのデータに関する公式リファレンス

//エラー判定を含めたJSON取得用の関数を作成
function ag2curl_gcalendar($url){
  $option = [
    CURLOPT_RETURNTRANSFER => true,//データを文字列に変換して返す
    CURLOPT_TIMEOUT        => 30//タイムアウト秒数
  ];
  $ch = curl_init($url);//cURLセッションを初期化
  curl_setopt_array($ch, $option);//転送用の複数のオプションを設定
  $json = curl_exec($ch);//cURLセッションを実行
  if(curl_errno($ch)){ //エラー番号を返す(エラーが発生しない場合、0)
    global $gcalendar_error;
    $gcalendar_error = '<p>cURL error '.curl_errno($ch).' : '.curl_error($ch).'</p>';
    $json = false;
  }
  curl_close($ch);//cURLセッションを閉じて処理を終了
  return $json;
}

//APIからJSONデータを取得
$json = ag2curl_gcalendar($gcalendar_api_url);

if($json){
  //予定イベントのデータを配列で保持
  $gcalendar_events = [];

  //JSON文字列をデコードして連想配列形式のオブジェクトを格納
  $obj = json_decode($json, true);

  @$globalscalendar_summary = $obj['summary'];//カレンダーの名前
  @$gcalendar_description = $obj['description'];//カレンダー説明
  @$gcalendar_updated = $obj['updated'];//カレンダー最終更新日
  @$gcalendar_timeZone = $obj['timeZone'];//カレンダーに設定されているタイムゾーン
  @$gcalendar_items = $obj['items'];//予定イベント(配列形式)

  if(!empty($gcalendar_items)){
    $gcalendar_items_num = count($gcalendar_items);
    for($i = 0; $i < $gcalendar_items_num; $i++){
      @$gcalendar_event_id = $gcalendar_items[$i]['id'];//予定のID
      @$gcalendar_event_link = $gcalendar_items[$i]['htmlLink'];//予定をGoogle Calendarで開くリンク
      @$gcalendar_event_title = $gcalendar_items[$i]['summary'];//予定のタイトル
      @$gcalendar_event_desc = $gcalendar_items[$i]['description'];//予定の本文(html形式)
      @$gcalendar_event_location = $gcalendar_items[$i]['location'];//場所
      @$gcalendar_event_start_date = $gcalendar_items[$i]['start']['date'];//開始日(終日指定の場合)
      @$gcalendar_event_start_time = $gcalendar_items[$i]['start']['dateTime'];//開始日時(時間指定の場合)
      @$gcalendar_event_end_date = $gcalendar_items[$i]['end']['date'];//終了日(終日指定の場合)
      @$gcalendar_event_end_time = $gcalendar_items[$i]['end']['dateTime'];//終了日時(時間指定の場合)

      //開始日時を調整
      if(!empty($gcalendar_event_start_time)){
        //終日設定ではない場合
        $all_day = false;
        $gcalendar_event_start_stamp = strtotime($gcalendar_event_start_time);
        $gcalendar_event_start_time = date('H:i', $gcalendar_event_start_stamp);
      }else{
        //終日設定の場合
        $all_day = true;
        $gcalendar_event_start_stamp = strtotime($gcalendar_event_start_date);
        $gcalendar_event_start_time = '終日';
      }
      $gcalendar_event_start_date = date('Y-m-d', $gcalendar_event_start_stamp);

      //終了日時を調整
      if(!empty($gcalendar_event_end_time)){
        //終日設定ではない場合
        $gcalendar_event_end_stamp = strtotime($gcalendar_event_end_time);
      }else{
        //終日設定の場合、翌日の00:00:00がendTimeになるので1秒戻す
        $gcalendar_event_end_stamp = strtotime($gcalendar_event_end_date) - 1;
      }
      $gcalendar_event_end_time = date('H:i', $gcalendar_event_end_stamp);
      $gcalendar_event_end_date = date('Y-m-d', $gcalendar_event_end_stamp);

      //取得したデータを配列で格納
      $gcalendar_events[$i] = array(
        'id' => $gcalendar_event_id,
        'link' => $gcalendar_event_link,
        'title' => $gcalendar_event_title,
        'desc' => $gcalendar_event_desc,
        'location' => $gcalendar_event_location,
        'allDay' => $all_day,
        'startDate' => $gcalendar_event_start_date,
        'startTime' => $gcalendar_event_start_time,
        'startStamp' => $gcalendar_event_start_stamp,
        'endDate' => $gcalendar_event_end_date,
        'endTime' => $gcalendar_event_end_time,
        'endStamp' => $gcalendar_event_end_stamp
      );
    }

    //取得したデータをHTMLに出力
    foreach($gcalendar_events as $k => $v){
      echo '<p>'.date('Y m/d (D)', $v['startStamp']).'</p>';
      echo '<p>'.$v['title'].'</p>';

      if($v['startDate'] === $v['endDate']){
        if($v['allDay']){
          echo '<p>[時間] '.$v['startTime'].'</p>';
        }else{
          echo '<p>[時間] '.$v['startTime'].' ~ '.$v['endTime'].'</p>';
        }
      }else{
        if($v['allDay']){
          echo '<p>[時間] '.date('Y m/d (D)', $v['startStamp']).' '.$v['startTime'].'</p>';
        }else{
          echo '<p>[時間] '.date('Y m/d (D)', $v['startStamp']).' '.$v['startTime'].' ~ '.date('Y m/d (D)', $v['endStamp']).' '.$v['endTime'].'</p>';
        }
      }

      if(!empty($v['location'])) echo '<p>[場所] '.$v['location'].'</p>';

      if(!empty($v['desc'])) echo '<p>[内容] '.$v['desc'].'</p>';
    }//foreach

  }else{
    echo '<p>次のスケジュールは未定です。</p>';
  }
}else{
  echo '<p>API エラー : 予定を読み込めませんでした。</p>';
  echo $gcalendar_error;
}

 

 

この記事をシェア
この記事のURL

https://memo.ag2works.tokyo/post-1343/

コピー
この記事のタイトル

Google Calendar APIのAPIキーとカレンダーIDでGoogleカレンダーのJSONデータを取得。 | memo メモ [AG2WORKS]

コピー
この記事のリンクタグ

<a href="https://memo.ag2works.tokyo/post-1343/" target="_blank" rel="noopener">Google Calendar APIのAPIキーとカレンダーIDでGoogleカレンダーのJSONデータを取得。 | memo メモ [AG2WORKS]</a>

コピー
※ フィールドをクリックでコピーするテキストの編集ができます。

この記事へのコメント

コメントの書き込みはまだありません。

  • コメント内のタグはエスケープ処理され、文字列として出力されます。
  • セキュリティーのため、投稿者のIPアドレスは取得されます。
  • 管理者が内容を不適切と判断したコメントは削除されます。
  • このフォームにはスパム対策として、Googleの提供するreCAPTCHAシステムが導入されています。
    (Google Privacy Policy and Terms of Service.)