Python

pythonでgoogle calendarの予定【勤怠】をエクセル形式で出力するプログラムを作る(主要データ取込み編)

こんにちは Tomoです。

前回に引き続きエクスポートしたカレンダーデータの読み込みを行います。

今回は読み込んだカレンダーファイルから、「勤怠」と時間「09:30~18:30」を取得してコンソールに取得します

  1. カレンダーデータからイベントデータを取得
  2. まとめ

カレンダーデータから予定(イベント)データを取得

前回の出力したデータからイベントデータを取得します。

  • BEGIN:VEVEN
  • DTSTART:20191228T003000Z
  • DTEND:20191228T093000Z
  • SUMMARY:勤怠
  • END:VEVENT

今回は上に記載されている値を出力します

『BEGIN:VEVEN』『END:VEVENT』はイベントの開始と終了です。この開始と終了が一つのイベントの単位となります。

『DTSTART:20191228T003000Z』と『DTEND:20191228T093000Z』は開始時間と終了時間です。

『SUMMARY:勤怠』はタイトルです。

コーディングは前回の続きで行います。

【変更前】

    
import zipfile

with zipfile.ZipFile('D:\\python_workspace\\imput_data\\{Google アカウント}@gmail.com.ical.zip') as cal_zip:
    with cal_zip.open('{xxxxxxxx}@group.calendar.google.com.ics') as cal_file:
        for lineline.decode('utf-8') in cal_file:
            print(line.decode('utf-8'))
    

【変更後】

  
import zipfile

with zipfile.ZipFile('D:\\python_workspace\\imput_data\\{Google アカウント}@gmail.com.ical.zip') as cal_zip:
    with cal_zip.open('{xxxxxxxx}@group.calendar.google.com.ics') as cal_file:

         for line in cal_file:

             line_decode = line.decode('utf-8')

             # イベントの開始(BEGIN:VEVENT)を探す
             if 'BEGIN:VEVENT' in line_decode:
                 print(line_decode)

             # イベントの終了(END:VEVENT)
             if 'END:VEVENT' in line_decode:
                 print(line_decode)
    

『line_decode = line.decode('utf-8')』

ファイルから1行取得するたびに「utf-8」の形式に変換します。

『if 'BEGIN:VEVENT' in line_decode:』条件構文で「line_deco『if 'END:VEVENT' in line_decode:』の条件を確認します。

この条件の処理が終わると再度『for line in cal_file:』に移動して2行目を処理します。

cal_fileの行の数だけ処理を繰り返します。

保存して実行します。

    
D:\python_workspace>python testpython.py
BEGIN:VEVENT

END:VEVENT
    

上記結果の通りイベントの開始と終了のみを抽出して出力することができました。

同様に、「タイトル」「開始時間」「終了時間」を表示します。

    
import zipfile

with zipfile.ZipFile('D:\\python_workspace\\imput_data\\{Google アカウント@gmail.com.ical.zip') as cal_zip:
    with cal_zip.open('{xxxxxxxx}@group.calendar.google.com.ics') as cal_file:

         for line in cal_file:

             line_decode = line.decode('utf-8')

             # イベントの開始(BEGIN:VEVENT)を探す
             if 'BEGIN:VEVENT' in line_decode:
                 print(line_decode)

             # 開始時間(DTSTART)を探す
             if 'DTSTART:' in line_decode:
                 print(line_decode)

             # 終了時間(DTEND)を探す
             if 'DTEND:' in line_decode:
                 print(line_decode)

             # タイトル(SUMMARY)を探す
             if 'SUMMARY:' in line_decode:
                 print(line_decode)

             # イベントの終了(END:VEVENT)
             if 'END:VEVENT' in line_decode:
                 print(line_decode)
    

先ほどと違って時間やタイトルは自由に変えることができるため、「:」の前の文字と一致したら表示するようにします。

実行します。

    
D:\python_workspace>python testpython.py
BEGIN:VEVENT
DTSTART:20191228T003000Z
DTEND:20191228T093000Z
SUMMARY:勤怠
END:VEVENT
    

これで必要な値の条件を取得することができましが、実際には『DTSTART』の『DTEND』の時刻が必要なのでこの2つを取得します。

また、『DTSTART』の『DTEND』はそれぞれ文字列です、このため、開始と終了の時間を求めるときにあまり適していません。

時刻の計算をするために、時間の型に変換したいと思います。

以下のように対応します。

    
import zipfile
import datetime
import dateutil.parser

with zipfile.ZipFile('D:\\python_workspace\\imput_data\\{Google アカウント}@gmail.com.ical.zip') as cal_zip:
    with cal_zip.open('{xxxxxxxx}@group.calendar.google.com.ics') as cal_file:

         jst = datetime.timezone(datetime.timedelta(hours=+9), 'JST')

         for line in cal_file:

             line_decode = line.decode('utf-8')
             line_decode = line_decode.rstrip('\r\n')

             # イベントの開始(BEGIN:VEVENT)を探す
             if 'BEGIN:VEVENT' in line_decode:
                 print(line_decode)

             # 開始時間(DTSTART)を探す
             if 'DTSTART:' in line_decode:
                 dt_start = line_decode.split(':')
                 dt_start_time = dateutil.parser.parse(dt_start[1]).astimezone(jst)
                 print(dt_start_time.strftime("%Y/%m/%d %H:%M:%S"))

             # 終了時間(DTEND)を探す
             if 'DTEND:' in line_decode:
                 dt_end = line_decode.split(":")
                 dt_end_time = dateutil.parser.parse(dt_end[1]).astimezone(jst)
                 print(dt_end_time.strftime("%Y/%m/%d %H:%M:%S"))

             # タイトル(SUMMARY)を探す
             if 'SUMMARY:' in line_decode:
                 summary = line_decode.split(':')
                 print(summary[1])

             # イベントの終了(END:VEVENT)
             if 'END:VEVENT' in line_decode:
                 print(line_decode)
    

『import datetime』『import dateutil.parser』日付を扱うためのライブラリをインポートします。

日付は「20191228T003000Z」このような形式でこれは、ISO-8601の国際表記のようです。これを時刻に直す場合は、「dateutil.parser」のライブラリを使います。

これを使う際にTimezoneの変換が必要です。このため、『jst = datetime.timezone(datetime.timedelta(hours=+9), 'JST')』を使用します。こちらについては、私もきちんと理解できなかったので、後日調べたいと思います。

『line_decode = line_decode.rstrip('\r\n')』これは改行コードを取ります。『\r\n』が開業コードです。

『 dt_start = line_decode.split(':')』『split』メソッドを使って『:』個の区切り文字で左側と右側に分けます。分けた値をdt_startに入れます。このとき『dt_start[0] = DTSTART』『dt_start[1] = 20191228T003000Z』このようにdt_startの変数に対して2つの値が設定されます。』

これはリストとよばれており、『dt_start = [DTSTART, 20191228T003000Z]これと同じ意味になるようです。

『dt_start_time = dateutil.parser.parse(dt_start[1]).astimezone(jst)』ここが私も一番難しかったです。dateutilのライブラリを使って文字列から時刻の型に変換しています。その際にタイムゾーンを使って日本時刻に変換しています。私ももう少し勉強します。

『dprint(dt_end_time.strftime("%Y/%m/%d %H:%M:%S"))』ここは時刻から文字に変換しています。この時出力のフォーマットを決めています。

以上が今回のコーディングです。

実際に動かしてみます。

    
D:\python_workspace>python testpython.py
BEGIN:VEVENT
2019/12/28 09:30:00
2019/12/28 18:30:00
勤怠
END:VEVENT
    

まとめ

今回は、カレンダーデータから必要な情報を取得し、「勤怠」と開始と終了時間「09:30~18:30」を取得しました。。

次回は、勤怠の複数の予定と、休憩時間の算出計算を行いたいと思います。