🌲
GoogleカレンダーとTimeTreeを自動連携するやり方(半自動)
🎯 目的
- 普段使っている Googleカレンダーの予定を TimeTreeでも見える化 したい
- 手作業のコピーや二重入力を避けて、 できるだけ工数を減らしたい
- 背景として、家族がTimeTreeを利用しているが自分はGoogleカレンダー一択なため、いちいちTimeTreeに予定を作成して共有するのがめんどくさかった
📝 課題と解決策
課題1:GoogleカレンダーからTimeTreeへ直接連携できない
解決策
- 「Googleカレンダー → iPhone標準カレンダー → TimeTree」のルートを構築
- iPhone標準カレンダーはGoogleカレンダーを取り込める
- TimeTreeはiPhoneカレンダーをインポートできる
👉 直接は無理でも、間に「別カレンダー」を挟むことで実現
課題2:過去の予定までコピーされてしまう
解決策
- GASで「今日以降の予定だけコピー」するように修正
課題3:毎月コピーすると同じ予定が重複する
解決策
- GASに「既存チェック」を追加
- タイトル+日時が同じ予定があればスキップ
課題4:プライベート予定まで詳細がコピーされる
解決策
- GASで「プライベート(private)の予定は『予定あり』に変換」
課題5:コピー内容が確認できない
解決策
- GASで「コピーした予定の日時+タイトルをログに出力」
課題6:予定を二重に入力する必要がある
解決策
- GASで「普段使うカレンダー → 共有用カレンダー」に自動コピー
- 普段はいつも通りメインカレンダーに予定を入れるだけでOK
✅ 解決策まとめ(やり方)
① Google Apps Script (GAS) プロジェクトを作成
- Google Apps Script を開く
- 新しいプロジェクトを作成
- 名前を「GoogleCalendar_Copy」などに変更
② Calendar API を有効化
- GASエディタ左メニュー → 「サービス(積み木マーク)」
- 「高度なGoogleサービス」をクリック
- Calendar API を「オン」にする
- さらに「Google Cloud Consoleを開く」を押して、そこでも Calendar API を有効化
👉 これで Calendar.Events.list
や Calendar.Events.insert
が使えるようになる
③ コピー用カレンダーを作成
- Googleカレンダーを開く
- 左の「+」→「新しいカレンダーを作成」
- 名前を「TimeTree同期用」などにする
- カレンダー設定 → 「カレンダー統合」→ カレンダーIDをコピー
④ コードを貼り付ける
function copyFutureEventsWithCalendarAPI() {
var sourceCalendarId = "primary"; // 元カレンダー(メインなら "primary")
var targetCalendarId = "your-target-calendar@group.calendar.google.com"; // コピー先カレンダーID
var today = new Date();
var end = new Date();
end.setFullYear(end.getFullYear() + 1);
// 元カレンダーからイベント取得
var events = Calendar.Events.list(sourceCalendarId, {
timeMin: today.toISOString(),
timeMax: end.toISOString(),
singleEvents: true,
orderBy: "startTime"
});
var copied = [];
var skipped = [];
for (var i = 0; i < events.items.length; i++) {
var ev = events.items[i];
var start = new Date(ev.start.dateTime || ev.start.date); // 終日対応
var endTime = new Date(ev.end.dateTime || ev.end.date);
var title = ev.summary || "(無題)";
// プライベートならタイトルを「予定あり」に変換
var copiedTitle = (ev.visibility === "private") ? "予定あり" : title;
// コピー先に同じ予定があるか確認
var existing = Calendar.Events.list(targetCalendarId, {
timeMin: start.toISOString(),
timeMax: endTime.toISOString(),
q: copiedTitle
});
if (existing.items && existing.items.length > 0) {
skipped.push(start.toLocaleString() + " - " + copiedTitle);
continue;
}
// コピー先に作成(privateの場合は場所・説明を入れない)
if (ev.visibility === "private") {
Calendar.Events.insert({
summary: "予定あり",
start: { dateTime: start.toISOString() },
end: { dateTime: endTime.toISOString() }
}, targetCalendarId);
} else {
Calendar.Events.insert({
summary: copiedTitle,
start: { dateTime: start.toISOString() },
end: { dateTime: endTime.toISOString() },
location: ev.location,
description: ev.description
}, targetCalendarId);
}
copied.push(start.toLocaleString() + " - " + copiedTitle);
}
// ログ出力
Logger.log("=== コピーした予定 ===");
copied.forEach(function(e) { Logger.log(e); });
Logger.log("=== スキップした予定 ===");
skipped.forEach(function(e) { Logger.log(e); });
Logger.log("コピー完了!新規コピー: " + copied.length + "件, スキップ: " + skipped.length + "件");
}
⑤ 実行テスト
- ▶ ボタンを押して
copyFutureEventsWithCalendarAPI
を実行 - 初回は「権限の承認」が必要 → 許可
- 「表示 → ログ」で「コピーした予定」と「スキップした予定」が出れば成功
⑥ 自動化(トリガー設定)
- GASエディタ左の「時計アイコン」 → 「トリガー」
- 「トリガーを追加」
- 関数:
copyFutureEventsWithCalendarAPI
- イベントのソース:時間主導型
- 時間ベース:月ベース、毎月1日など
- 関数:
- 保存
👉 毎月自動で「今日以降1年分」をコピー
⑦ TimeTreeで表示
- iPhoneの標準カレンダーに「コピー先カレンダー」を追加
- 設定 → カレンダー → アカウント → Googleアカウント → 同期するカレンダーにチェック
- TimeTreeアプリで「iPhoneカレンダーからインポート」を設定
👉 これで自動的にTimeTreeに予定が反映される
🔄 最終的な運用フロー
- 普段は Googleカレンダー(メイン) に予定を入力するだけ
- GASが毎月1日に自動実行 → 「今日以降1年分」を別カレンダーにコピー
- 重複チェックあり
- プライベート予定は「予定あり」に変換
- コピー内容はログで確認可能
- iPhone標準カレンダーにその「別カレンダー」を読み込む
- TimeTreeでiPhoneカレンダーを定期的にインポート → TimeTreeにも反映
📝 まとめ
今回GPTを使って試行錯誤しながらやってみました。
非エンジニアですが、GPTを使えば30分くらいでそれっぽく動く仕組みを作ることができました。
エンジニアの方なら、完全に自動化まで持っていけるんですかね…。
自分ももっと精進します💪
Discussion