現在、知り合いのクソみたいな要件のアプリを開発中。アルゴ的には実現ハードルが高すぎるので、使えるものにはならないと思うが、勉強ついでに手伝っている。今回は、その一歩として、「Google Calendar APIを使って、自分のカレンダーの予定を取得する」 ところまでを実装する。備忘録として、その方法を記載する。
Google Cloud Platform (GCP) での準備
まずは、Googleと通信する事ができないと始まらないので、そこら辺の設定をする。どうやら、Google Cloud Platformというのを使えばできるらしい。
Google Cloud Platform
Google Cloud Platform (GCP) とは、Google が提供するクラウドコンピューティングのプラットフォームです。インターネット経由で、データストレージ、コンピュータリソース、ネットワーキング、ビッグデータ、AIツールなどを使うことができるサービスをまとめたものです。
初心者の方でも理解しやすいように言うと、GCPはあなたのビジネスやプロジェクトのために、必要なデジタル環境を整えるための道具箱のようなものです。例えば、ウェブサイトのホスティング、アプリのバックエンド、データの保存や解析など、さまざまな用途に使われます。
https://www.kiyono-co.jp/post/google-cloud-platform
初心者の僕にはよくわからん。まぁ、Google Cloudを使うためのPlatformなわけで、これを使うことで、Google Cloudがつかえるわけだ。
プロジェクトの作成
Google Cloud Console にアクセスする。左上のプロジェクト選択プルダウンから「あたらしいプロジェクト」を作成する(名前は適当でよい)。
APIの有効化
プロジェクトを作ったら、次はAPIを有効化する必要がある。
「APIとサービス」 > 「ライブラリ」へ移動して、検索バーに Google Calendar API と入力。
Google Calendar APIを有効にする。
OAuth同意画面の設定
今回はお試しなので、appとかではなくて、ローカルPCで動かすものとして認証する。その前にOAuthとはなにか
OAuth
ユーザーはIDやパスワードを直接そのサービスに渡す必要はなく、かわりにGoogleやTwitterなど信頼できる提供元に一度だけ認証してもらい、その“証明書”を相手のサービスに提示することでアクセスが可能になります。これにより、複数のサービスで同じパスワードを入力するリスクを避けることができ、利便性と安全性を両立できるというわけです。
https://auth0.com/jp/intro-to-iam/what-is-oauth-2
あんまりよくわかってないが、ここらへんが概念的にはわかりやすい。要はユーザーがパスワードとかの認証をしなくても、ユーザが過去認証したことのある手段を中間的に用いて、ユーザの認証をスキップする事ができる。というふうに理解している。
「APIとサービス」 > 「OAuth同意画面」へ。
User Type は 「外部 (External)」 を選択して、アプリ名とメールアドレスを入力して保存。
テストユーザーの追加
これだけでは、現在アプリはテスト環境にあるらしく、テスト環境は一部の人間しか触ることができない。そのため、この一部の人間というのを登録する必要がある。
「APIとサービス」 > 「OAuth同意画面」 > 「対象」へ。
「テストユーザ」の欄で、自分のGoogleアカウント(Gmailアドレス)を追加する。これを忘れると Error 403: access_denied で弾かれます。
認証情報 (Credentials) の作成
「APIとサービス」 > 「認証情報」へ。
「認証情報を作成」 > 「OAuth クライアント ID」 を選択する。アプリケーションの種類は「デスクトップ アプリ」とする。
作成したら、JSONファイルをダウンロードというボタンを押して、JSONファイルをダウンロードする。ダウンロードされたものをcredentials.json という名前にリネームして、ローカルのプロジェクトフォルダに配置する。
Python環境の構築
実際にデータを受け取るプログラムを考える。言語としてはPythonを採用して、環境はuvで構築する。
# プロジェクト作成
mkdir project_name
cd project_name
uv init
# 必要なライブラリのインストール
uv add google-api-python-client google-auth-httplib2 google-auth-oauthlib
予定を取得するコード
実際に予定を受け取るコードを書いていく。と言ってもLLMに書いてもらったので、さして理解していない。どうやら、日付を引数にすることで、指定された期間の予定を取ってくる事ができるらしい。
import datetime
import json
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
# 読み取り専用スコープ(書き込みたい場合は .readonly を外す)
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
def get_calendar_events(days=7):
creds = None
# 1. 以前の認証情報があればロード
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# 2. 認証情報がない、または期限切れならログイン画面を出す
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# 次回用に保存
with open('token.json', 'w') as token:
token.write(creds.to_json())
# 3. APIクライアントの構築
service = build('calendar', 'v3', credentials=creds)
# 4. 取得範囲の設定(現在時刻〜指定日数後まで)
now = datetime.datetime.utcnow()
time_min = now.isoformat() + 'Z'
time_max = (now + datetime.timedelta(days=days)).isoformat() + 'Z'
print(f"🔍 取得範囲: {time_min} 〜 {time_max}")
# 5. データ取得実行
events_result = service.events().list(
calendarId='primary',
timeMin=time_min,
timeMax=time_max,
singleEvents=True,
orderBy='startTime'
).execute()
events = events_result.get('items', [])
# 6. 結果の表示
if not events:
print("予定はありません。")
else:
print(f"✅ {len(events)} 件の予定が見つかりました。\n")
# 最初の1件だけ生データを表示してみる
print(json.dumps(events[0], indent=2, ensure_ascii=False))
if __name__ == "__main__":
get_calendar_events(days=7)
実行結果とデータの構造
実行するとブラウザが立ち上がり、Googleアカウントでのログインを求められます。許可すると、コンソールにデータが表示されます。
取得できた生データ(抜粋)
{
"kind": "calendar#event",
"id": "abcde12345...",
"status": "confirmed",
"summary": "朝ごはんを食べる",
"description": "納豆・卵かけご飯",
"start": {
"dateTime": "2026-02-09T08:00:00+09:00",
"timeZone": "Asia/Tokyo"
},
"end": {
"dateTime": "2026-02-09T08:30:00+09:00",
"timeZone": "Asia/Tokyo"
}
}
それぞれのデータの意味
-
kind: データの種類。「calendar#event」はこれが「カレンダーの予定」であることを示す -
etag: データが変更されたかを識別するためのタグ -
id: この予定を特定するための固有ID -
status: 予定の状態。confirmed は「確定済み(キャンセルされていない)」という意味 -
htmlLink: ブラウザでこの予定を開くためのURL -
created: この予定が最初に作られた日時 -
updated: この予定が最後に更新された日時 -
summary: 予定のタイトル -
description: メモ・詳細 -
creator: 予定を作成した人(メールアドレス)。self: true は自分自身であることを示します -
organizer: 予定の主催者(カレンダーの所有者) -
start: 開始日時 -
dateTime: 日時(日付と時刻) -
timeZone: タイムゾーン -
end: 終了日時 -
dateTime: 日時(日付と時刻) -
iCalUID: 異なるカレンダーシステム間で連携するためのID -
sequence: 変更回数 -
reminders: 通知設定。useDefault: true はカレンダーのデフォルト設定を使うという意味 -
eventType: 予定のタイプ。default は通常の予定
