年始ということでおおまかな目標をカレンダーに記しておきたいという人も多いのではないだろうか。おろしたての新手帳やカレンダーにペンで目標計画を入れるには最適な時期だ。
デジタルでも同様の所作を手軽にできないだろうか?そう思った。Googleカレンダーをはじめ、デジタルカレンダー機能を持つサービスはクラウドで連動するので、一度PCで書き込めば、それがスマホやタブレットでも確認できるようになる。

PCからのカレンダー入力をさらに手早く行えれば、こまめなスケジューリング登録も億劫(おっくう)にならない。正月の期間、飽くなき利便性にチャレンジしてみようとクリップボードからカレンダーを入力できないかを考えた。

テキストエディターなどのコピー&ペーストで頻繁に使用するクリップボードには直前にコピーした文字列が格納されている。これを抜き出して、カレンダーサービスに文字列を渡せれば、わざわざブラウザを立ち上げなくてもカレンダー入力できる利便性がある。
○GoogleカレンダーAPIをPythonから制御する

Googleカレンダーを取り扱うには、こちらの連載(ゼロからはじめるPython Googleカレンダーの予定を読み込んでカウントダウンしよう(上)カレンダー編 )を参考にPythonを使う。現在ではGoogle APIの仕様が異なっているが、import文にfrom google.oauth2 import service_accountを加えて、credentials = service_account.Credentials.from_service_account_file( CREDENTIALS_PATH, scopes=SCOPES)に変更すると読み込める。

import datetime
from googleapiclient.discovery import build
from google.oauth2 import service_account

# クレデンシャルファイルのパス
CREDENTIALS_PATH = "credentials.json"
# カレンダーID
CALENDAR_ID = "●●●●ad8807a52@group.calendar.google.com"
# スコープ
SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"]

# クレデンシャルの読み込み
credentials = service_account.Credentials.from_service_account_file(
CREDENTIALS_PATH, scopes=SCOPES
)

# APIクライアント作成
service = build("calendar", "v3", credentials=credentials)

# 期間指定
now = datetime.datetime.utcnow()
start_date = now.isoformat() + "Z"
end_date = (now + datetime.timedelta(days=30)).isoformat() + "Z"

# イベント取得
events_result = service.events().list(
calendarId=CALENDAR_ID,
timeMin=start_date,
timeMax=end_date,
singleEvents=True,
maxResults=30,
orderBy="startTime",
).execute()
events = events_result.get("items", [])

# 表示
if not events:
print("イベントは見つかりませんでした。")
else:
print("イベント一覧:")
for event in events:
target_date = event["start"].get("dateTime", event["start"].get("date"))
if "T" in target_date:
target_date = target_date[:10]
today = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
target_td = datetime.datetime.strptime(target_date, "%Y-%m-%d")
days = (target_td - today).days
print(f"{days:2}日 - {event['summary']}")

○実用度が高いと思ったスクリプトはエイリアスで呼び出しやすくしておこう

カレンダーをコンソールから読み込めるのも非常に便利だ。実用度が高いと思ったスクリプトはあとから忘れないようショートカットやコマンド化してしまうのが良い。ここではPowerShellのエイリアスとして登録してコマンドのように扱えるようにしてしまおう。
PowerShellで

notepad $PROFILE

と入力すると開くプロフィールファイルに、自身が設置している場所を追記して上書き保存する。

function goocal {
python "C:\Users\user\OneDrive\ドキュメント\script\n111.py"
}

これでコンソールからエイリアス名"goocal"と入力するけでPythonスクリプトが読み込まれる。ただしPythonファイルのCREDENTIALS_PATH = "credentials.json"の部分を相対パスから絶対パスへと変えておかないとcredentials.jsonの読み込みエラーが出る場合がある。

"goocal"と入力するだけでカレンダー逆算表示。独自のコマンドのように振る舞うので、頻繁に使うスクリプトに命名しておけばコマンド活用も進む。
○カレンダー入力用にカスタマイズする

次に、PythonスクリプトをGoogleカレンダー入力用にカスタマイズする。スコープの範囲をcalendar.readonlyからcalendarに変更し、書き込み可能に変えて、service.events().insert(calendarId=CALENDAR_ID, body=event).execute()を加えることで、読み取りではなく書き込みが可能になる。ポイントはクリップボードの扱いになるが、タイトル以外に日時を渡すには、どうしても数字が必要だ。あらかじめ、01100700ツーリング(1月10日7時ツーリング)のように、テキストエディタに入力してからこれをコピーする。前の8桁で月日時、残り文字列をタイトルに入れようというわけだ。

01100700ツーリング

Pythonからクリップボードのやりとりを行えるpyperclipライブラリをimport文(pip install pyperclip)に加えて、Pythonのスライスで日時とタイトルを切り分けてカレンダーの仕様に格納する。

import datetime
import pyperclip
from googleapiclient.discovery import build
from google.oauth2 import service_account

CREDENTIALS_PATH = "credentials.json"
CALENDAR_ID = "●●●●●@gmail.com"
SCOPES = ["https://www.googleapis.com/auth/calendar"]

credentials = service_account.Credentials.from_service_account_file(
CREDENTIALS_PATH, scopes=SCOPES
)
service = build("calendar", "v3", credentials=credentials)

# クリップボードから文字列取得
clip_text = pyperclip.paste().strip()

# Pythonのスライス構文で先頭8文字を日時、残りをタイトルとする 例01100700ツーリング
date_str = clip_text[:8]
title = clip_text[8:].strip()

# MMDDHHMM を分解
month = int(date_str[0:2])
day = int(date_str[2:4])
hour = int(date_str[4:6])
minute= int(date_str[6:8])

year = datetime.date.today().year

start_dt = datetime.datetime(year, month, day, hour, minute)
end_dt = start_dt + datetime.timedelta(hours=1)

event = {
"summary": title,
"start": {"dateTime": start_dt.isoformat(), "timeZone": "Asia/Tokyo"},
"end": {"dateTime": end_dt.isoformat(), "timeZone": "Asia/Tokyo"},
}

created_event = service.events().insert(calendarId=CALENDAR_ID, body=event).execute()
print(f"イベントを作成しました: {created_event.get('htmlLink')}")

.
編集部おすすめ