この記事は Wano Group Advent Calendar 2023 の16日目の記事です。
概要
最近Copilotの使い方を学び始めました。
ちょうどチームメンバーの日程調整機能を作りたいので、Google Calendar APIとCopilotを使って作ってみました。
先ずはgolangでGoogle Calendar APIを使う
google提供のクイックスタートを通りにやっていくだけで、個別のカレンダー情報を取得できます。さらに、calendar/v3/freeBusy API は複数メンバーのカレンダーの予定時間情報を返します:
jst, _ := time.LoadLocation("Asia/Tokyo")
events, err := srv.Freebusy.Query(&calendar.FreeBusyRequest{
Items: []*calendar.FreeBusyRequestItem{
{
Id: "XXXXX1@gmail.com", // メンバー1カレンダーのメールアドレス
},
{
Id: "XXXXX2@gmail.com", // メンバー2カレンダーのメールアドレス
},
},
// クエリの間隔の終了時刻
TimeMax: time.Date(2023, month, days, 24, 0, 0, 0, jst).Format(time.RFC3339),
// クエリの間隔の開始時刻
TimeMin: time.Date(2023, month, 1, 0, 0, 0, 0, jst).Format(time.RFC3339),
// レスポンスで使用されるタイムゾーン
TimeZone: "Asia/Tokyo",
}).Do()
しかし、複数対象の共通空き時間を取得するAPIがあるかどうかを探しましたが、
残念ですが、そのような機能は提供されていないようですので、この関数を自分で実装してみる。
// 1ヶ月の分を確認
for day := 1; day < days; day++ {
// 確認したいの時間帯 12:00-13:00 / 12:30-13:30 / 13:00-14:00
checkTimeStructs := make([]CheckTimeStruct, 0)
checkTimeStructs = append(checkTimeStructs, CheckTimeStruct{
StartTime: time.Date(2023, month, day, 12, 0, 0, 0, jst),
EndTime: time.Date(2023, month, day, 13, 0, 0, 0, jst),
IsUsable: true,
})
checkTimeStructs = append(checkTimeStructs, CheckTimeStruct{
StartTime: time.Date(2023, month, day, 12, 30, 0, 0, jst),
EndTime: time.Date(2023, month, day, 13, 30, 0, 0, jst),
IsUsable: true,
})
checkTimeStructs = append(checkTimeStructs, CheckTimeStruct{
StartTime: time.Date(2023, month, day, 13, 0, 0, 0, jst),
EndTime: time.Date(2023, month, day, 14, 0, 0, 0, jst),
IsUsable: true,
})
// 土日は除外
if checkTimeStructs[0].StartTime.Weekday() == 0 || checkTimeStructs[0].StartTime.Weekday() == 6 {
continue
}
// メンバーの予定を確認
for _, item := range events.Calendars {
for index, _ := range checkTimeStructs {
// 日付が範囲内にあるかどうかの確認関数
if checkDateInPeriod(item.Busy, checkTimeStructs[index].StartTime, checkTimeStructs[index].EndTime) {
checkTimeStructs[index].IsUsable = false
}
}
}
//結果を出力
for index, single := range checkTimeStructs {
if index == 0 && single.IsUsable {
fmt.Printf("%d日の12:00-13:00は空いています。\n", day)
}
if index == 1 && single.IsUsable {
fmt.Printf("%d日の12:30-13:30は空いています。\n", day)
}
if index == 2 && single.IsUsable {
fmt.Printf("%d日の13:00-14:00は空いています。\n", day)
}
}
}
}
よく使うの関数はCopilotに補完
補完の機能について、基本の操作はこの感じ:
Command + → -> ワードごとの適用
Tab -> サジェスト内容を適用する
Esc -> サジェスト内容を棄却出来る
それを使って時間帯確認周りの関数が簡単に作られた
// 時間帯が範囲内にあるかどうか
func checkDateDuplicated(inStart time.Time, inEnd time.Time, targetStart time.Time, targetEnd time.Time) bool {
if inStart.Before(targetEnd) && targetStart.Before(inEnd) {
return true
}
return false
}
// 日付が範囲内にあるかどうか
func checkDateInPeriod(in []*calendar.TimePeriod, targetStart time.Time, targetEnd time.Time) bool {
if len(in) == 0 {
return false
}
for _, v := range in {
start, _ := time.Parse(time.RFC3339, v.Start)
end, _ := time.Parse(time.RFC3339, v.End)
if checkDateDuplicated(start, end, targetStart, targetEnd) {
return true
}
}
return false
}
// うるう年の判定
func isLeapYear(year int) bool {
if year%400 == 0 {
return true
} else if year%100 == 0 {
return false
} else {
return year%4 == 0
}
}
// 月の日数を返す
func daysInMonth(year int, month time.Month) int {
switch month {
case time.February:
if isLeapYear(year) {
return 29
} else {
return 28
}
case time.April, time.June, time.September, time.November:
return 30
default:
return 31
}
}
以上の関数は全部Copilotで生成された、結構楽ですね!
最後に
出力した結果がこちらです。
いい感じでみんなの空き日時を抽出することを出来ました。
今回はGoogle Calendar API x Copilotを活用して簡易な日程調整を作成しました。
こういう組み合わせると意外と面白いことができると思います。
現在、Wanoグループでは人材募集をしています。興味のある方は下記を参照してください。
JOBS | Wano Group