はじめに
「札幌市ICT活用プラットフォーム DATA-SMART CITY SAPPORO」ってご存知ですか?
札幌市とさっぽろ産業振興財団が共同運営する「札幌市ICT活用プラットフォーム DATA-SMART CITY SAPPORO」は、データを活用してイノベーションを創出するための共通基盤として、官民が保有するオープンデータやビッグデータの収集・管理・提供を行っています。また、本サイト掲載データはCKAN標準APIでの活用も可能となっています。
ということなのですが、ここで「札幌市家庭ごみ収集日カレンダー」というものが公開されています。
これをGoogleカレンダーに取り込めるようにしてみよう、というのが今回の内容です。
データの確認
さっそくですが、実際に公開されているデータを見てみましょう。
日付,曜日,中央区1,中央区2,中央区3,中央区4,中央区5,中央区6,豊平区1,豊平区2,豊平区3,豊平区4,清田区1,清田区2,北区1,北区2,北区3,北区4,北区5,北区6,東区1,東区2,東区3,東区4,東区5,東区6,白石区1,白石区2,白石区3,白石区4,厚別区1,厚別区2,厚別区3,厚別区4,南区1,南区2,南区3,南区4,南区5,南区6,南区7,西区1,西区2,西区3,西区4,手稲区1,手稲区2,手稲区3
2017-10-01,日,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
2017-10-02,月,1,1,1,10,9,8,10,8,9,1,1,1,1,1,1,10,8,9,1,1,1,10,8,9,9,2,8,1,1,1,1,1,1,1,1,11,9,9,8,1,1,1,9,8,11,8
2017-10-03,火,8,10,9,1,1,1,1,1,1,10,9,8,9,10,8,1,1,1,10,8,9,1,1,1,1,1,1,8,9,9,8,2,9,11,8,1,1,1,1,9,11,8,1,1,1,1
…
日付,曜日,中央区1,中央区2,中央区3,中央区4,中央区5,中央区6,豊平区1,豊平区2,豊平区3,豊平区4,清田区1,清田区2,北区1,北区2,北区3,北区4,北区5,北区6,東区1,東区2,東区3,東区4,東区5,東区6,白石区1,白石区2,白石区3,白石区4,厚別区1,厚別区2,厚別区3,厚別区4,南区1,南区2,南区3,南区4,南区5,南区6,南区7,西区1,西区2,西区3,西区4,手稲区1,手稲区2,手稲区3
2019-10-1,火,8,10,9,1,1,1,1,1,1,10,9,8,9,10,8,1,1,1,10,8,9,1,1,1,1,1,1,8,9,9,8,11,9,2,8,1,1,1,1,9,2,8,1,1,1,1
2019-10-2,水,10,9,8,9,8,10,9,10,8,8,10,9,10,8,9,9,10,8,9,10,8,9,10,8,11,8,9,11,8,11,11,9,8,9,2,8,8,2,9,8,9,2,2,9,8,2
…
1行目が各列の項目名、2行目以降が日毎の地域ごとのゴミ種別をIDで示したものになります。
1行目の3列目以降の「中央区1」「中央区2」…はこちらで記載されている地域番号ですね。
2行目以降のゴミ種別IDは「ごみ種別・番号対応表」としてまとめられている番号です。
記号,ごみ種
1,燃やせるごみ
2,燃やせないごみ
8,びん・缶・ペット
9,容器プラ
10,雑がみ
11,枝・葉・草
空欄,収集なし
実装方針
まず今回はPythonで、というのを決めた上で、確認したデータをもとに、以下の方針で実装することにしました。
入力
- 札幌市家庭ごみ収集日カレンダーのCSV
- CSV読みは楽をするためにpandasを利用することにします。明らかにオーバースペックですが
- 地域番号
- 地域番号はコマンドラインオプションで入力。
- ゴミ種別・番号対応表はソース内に直接抱えることにします
出力
- iCalendar形式で標準出力
- googleカレンダーに取り込むにはこの形式が定番ですね。
- icalendarというライブラリを利用することにします。私のicalendar記事だと必ず使っているライブラリです。
実装内容
以下の通り。githubにもおいてあります。
"""札幌市家庭ごみ収集日カレンダーのical化.
札幌市家庭ごみ収集日カレンダーをicalにする.
元ファイルは以下を参照.
https://ckan.pf-sapporo.jp/dataset/garbage_collection_calendar
"""
import sys
from argparse import ArgumentParser, FileType
import dateutil.parser
import pandas
from icalendar import Calendar, Event, vDate
def main():
"""メイン関数."""
p = ArgumentParser(description='札幌市家庭ゴミ収集日カレンダーCSVをical化する')
p.add_argument('-a', '--area', help='地域名')
p.add_argument(
'input',
type=FileType(encoding='utf-8'), help='札幌市家庭ゴミ収集日カレンダーCSV')
args = p.parse_args()
df = pandas.read_csv(args.input, dtype='object')
if args.area is None:
print('入力可能な地域名:', file=sys.stderr)
for area in df.columns[2:]:
print(' ' + area, file=sys.stderr)
return
if args.area not in df.columns[2:]:
print('地域名が見つかりません.', file=sys.stderr)
return
gctypes = {
'1': '燃やせるゴミ',
'2': '燃やせないゴミ',
'8': 'びん・缶・ペット',
'9': '容器プラ',
'10': '雑がみ',
'11': '枝・葉・草'
}
ical = Calendar()
for datestr, gctype in zip(df['日付'], df[args.area]):
if gctype in gctypes:
dt = dateutil.parser.parse(datestr)
event = Event()
event.add('SUMMARY', gctypes[gctype])
event.add('DTSTART', vDate(dt))
event.add('DTEND', vDate(dt))
event.add('TRANSP', 'TRANSPARENT')
ical.add_component(event)
print(ical.to_ical().decode('utf-8'))
if __name__ == '__main__':
main()
大したことはやっていませんが、1点だけハマった点。
- 札幌市家庭ごみ収集日カレンダー(2017年10月1日~2019年10月8日)の日付
- 「2017-10-01」となっており、ISO 8601形式(YYYY-MM-DD形式)になっている
- 札幌市家庭ごみ収集日カレンダー(2019年10月1日~2020年9月30日)の日付
- 「2019-10-1」となっており微妙にISO 8601からは外れてる…
ということで、2019年10月1日~2020年9月30日の方のファイルは、date.fromisoformat()を直接使えません。
このため、python-dateutilのdateutil.parser.parse()を使用するようにしています。
おわりに
今回のツールを使って生成したicalendar形式ファイルをgoogleカレンダーにインポートすればおしまい。
googleカレンダーに入れてしまえば、色々通知にも使えますので、便利に使えますね。