Google Calendar APIを使って月末申請の交通費を自動計算してみた

# 目的
　だんだんと在宅勤務にも慣れてきましたが、週に何日かは出社して働いています。弊社は出社日数分×往復の交通費を月末に申請するスタイルなのですが、今月何日出社したっけ？片道の交通費っていくらだっけ？と都度計算するのは面倒ですよね。（え、そんなことはない？）

　そこで今回、Google Calendar APIとPythonを使って交通費の自動計算するプログラムを作ってみました。

計算するための条件として、出社日はGoogle Calendarに「出社」と記載するとしています。↓こんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2298484/a0c35030-3a6e-34c7-0f26-ab9fc1ba3e07.png)

# 手順

1. Google Calendar APIの有効化や認証情報の取得。
    a. こちらを参考に設定した。https://qiita.com/lobmto/items/c1a220a12ec9c1fad560
b. 設定後のフォルダ構成はこのようになる。credentials.jsonとtoken.jsonがないとプログラムが動かないので注意。quickstart.pyをcacl_transpot_expences.pyに変更（ファイル名は何でも良い）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2298484/64ab0c11-b217-341c-86ca-50075753b350.png)

2. 初期プログラムの中身を確認すると、いろいろ書いてあるがeventsリストで指定した期間のイベントを取得している。計算する月は任意にしたいので、引数として年、月を与えると指定した月のイベントを取得するようなget_events関数を作成。交通費を計算するcalculate_transportation_expenses関数では、get_events関数で取得したイベントリストと片道の交通費を引数として与える。
「出社」となっているイベントの日数をリストから数え、出社日数×片道の交通費×２でその月の交通費を求める。コードは下記の通り。
```python:calc_transport_expences.py
from __future__ import print_function
import datetime
from datetime import date, timedelta
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from pyasn1.type.univ import Null

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']

#引数を指定しなければ今月情報を取得する
#引数に月・年を指定すればその月の情報を取得する
def get_events(this_month=date.today().month, this_year=date.today().year):
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # If there are no (valid) credentials available, let the user log in.
    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)
        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    service = build('calendar', 'v3', credentials=creds)

    # Call the Calendar API
    first_day = date(this_year, this_month, 1)
    end_day = date(this_year, this_month+1, 1) - datetime.timedelta(days=1)
    

    events_result = service.events().list(calendarId='primary',
                                          timeMin=str(first_day)+"T00:00:00+00:00",
                                          timeMax=str(end_day)+"T00:00:00+00:00",
                                          singleEvents=True,
                                          orderBy='startTime').execute()
    events = events_result.get('items', [])

    return events

#グーグルカレンダーから取得した情報と片道の交通費を引数にして、月の交通費を計算する
def calculate_transportation_expenses(events, one_way_transportation_expenses):
    go_company_days = []
    month_transportation_expenses = 0

    for event in events:
        date = event['start'].get('date')
        if date != None and event['summary'] == "出社":
            #print(date, event['summary'])
            go_company_days.append(date)
    
    #print(len(go_company_days))
    month_transportation_expenses = 2 * one_way_transportation_expenses * len(go_company_days)

    return month_transportation_expenses, len(go_company_days)

if __name__ == '__main__':
    print("===交通費を求める===")
    expences = input('片道の交通費： ')
    #expences = 349
    this_year = input('求めたい年： ')
    this_month = input('求めたい月： ')

    month_events = get_events(int(this_month), int(this_year))
    month_transportation_expenses, go_company_days = calculate_transportation_expenses(month_events, int(expences))

    #print(month_transportatin_expenses)
    print("")
    print("===結果===")
    print("{0}年{1}月の交通費：{2}円".format(this_year, this_month, month_transportation_expenses))
    print("出社日数：{0}日".format(go_company_days))
```

# 結果
　ファイルを実行すると「片道の交通費」、「求めたい年」、「求めたい月」が聞かれるので、入力すると結果が返ってくる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2298484/498a7937-6b14-17d5-3624-ed0a033d4adb.png)

# まとめ
このスクリプトは実際には結構前に作成したものなのですが、個人的にちょくちょく使っているので今回Qiita記事としてまとめました。本当はGoogle Calendarのlocationから場所を取得して会社なら出社日として計算したいのですが、うまくいきませんでした。（ご存知の方がいましたら教えていただけると嬉しいです・・・！）