第1、第3、第5の月曜日の9時~12時といったスケジュールが多いのだが、Googleカレンダーで繰り返し予定として登録するのは無理だ。1年分登録するとなると25回も繰り返す羽目になるし、このような予定が数種類あるので途方もない作業量になる。面倒なことはPythonにさせてみよう・・・・ということで書いてみた。
GoogleカレンダーAPIにアクセスするのは面倒なので、GoogleカレンダーにインポートできるCSVファイルを作るのを目標とする。
import pandas as pd
import datetime
def generate_appoints(start, end, weekday, odd, start_time, end_time, offset_days = 0):
"""
start, endの間で条件に合うdatetime.datetimeのタプルを返す。
start, end: datetime.date
weekday: int datetime.date.weekday()の戻り値で曜日を指定
odd: bool 奇数週ならTrue
start_time, end_time: datetime.time()
offset_days: int 指定日の前日なら1
"""
dates = [start + datetime.timedelta(days = x) for x in range(0, (end - start).days)]
wdays = list(filter(lambda x: x.weekday() == weekday, dates))
wdays_select = list(filter(lambda x: ((x.day-1) // 7 + 1) % 2 == odd, wdays))
# 偶数、ないし奇数週の日付を抽出する x.day から1を引かないとxx月7日の判定がおかしくなる
start_dt = [datetime.datetime.combine(x - datetime.timedelta(days = offset_days),
start_time) for x in wdays_select]
end_dt = [datetime.datetime.combine(x, end_time) for x in wdays_select]
return (start_dt, end_dt)
generate_appoints()
は条件に合うdatetime.datetime
のタプルを返してくれる。これをpd.DataFrame
に整形する。
def generate_pd(subject, tp):
"""
開始日、終了日のタプルを受け取りpd.DataFrameを作る
"""
df = pd.DataFrame({"Subject": subject,
"Start Date": [x.date() for x in tp[0]],
"Start Time": [x.time() for x in tp[0]],
"End Date": [x.date() for x in tp[1]],
"End Time": [x.time() for x in tp[1]]})
return df
試しに第1,3,5月曜日のhoge1と第2、第4金曜のhoge2の予定表を作ってみる。
if __name__ == "__main__":
start = datetime.date(2019, 6, 3)
end = datetime.date(2020, 3, 31)
hoge1 = generate_appoints(start, end, 1, True, datetime.time(18, 0), datetime.time(19, 0), 1)
hoge2 = generate_appoints(start, end, 4, False, datetime.time(9, 0), datetime.time(15, 30))
hoge1_df = generate_pd("hoge1", hoge1)
hoge2_df = generate_pd("hoge2", hoge2)
final = hoge1_df.append(hoge2_df)
final.to_csv("2019_appointments.csv", encoding = 'utf_8_sig', index = False)
出力されたCSVをGoogleカレンダーにインポートすると狙った通りに予定が登録されている。ただ、祝日や代休のことは考慮されていない。手動で消すのは大した手間でないのでまあいいだろう。