さて、GoogleカレンダーのエクスポートをCSVにする。では浅瀬でパシャパシャやってただけなので、もうちょっと深いところまでいってみましょう。
まずデータを読み込みます。前回と同じデータですが、文字化けしている部分(どうもカレンダーを作成したアプリの不具合らしく、DESCRIPTIONのところのエンコードが壊れてた)はあらかじめ削除してあります。
>>> import ics
>>> with open('chiyo.ics', encoding='utf-8') as f:
... cals = ics.Calendar(f.read())
>>> cals
<Calendar with 1663 events>
>>> cals.events[5]
<Event '岡山出張' begin:2008-12-10T00:00:00+00:00 end:2008-12-12T00:00:00+00:00>
with
文を使うと、ブロックを抜けたときに自動的にファイルをclose()
してくれるので便利です。次に、それぞれのデータの値を見てみます。
>>> cals.events[5].name
'岡山出張'
>>> cals.events[5].begin
<Arrow [2008-12-10T00:00:00+00:00]>
>>> cals.events[5].end
<Arrow [2008-12-12T00:00:00+00:00]>
>>> cals.events[5].location
''
設定されていない空の項目は '' と空の値を返してくるようなので、同じメソッドで扱えそうです。ところでここで、
Arrow
というキーワードが出てきました。前回は「日時が出てきたね、よしよし」と気にもとめなかったのですが、Arrow: better dates and times for Pythonという、Pythonのdatetime
モジュールをさらに改良したようなものらしいです。PyPiはこちら。Arrow
を継承したオブジェクトは to()
とか humanize()
とかのファンクションが使えるようです。>>> local=cals.events[5].begin.to('Asia/Tokyo')
>>> local
<Arrow [2008-12-10T09:00:00+09:00]>
>>> local.humanize()
'9 years ago'
>>> local.humanize(locale='ja_jp')
'9年前'
なかなかに多芸です。ちなみに
to()
のパラメータはtimezone形式で、IANAのTime Zone Databaseで定義されています。#code coordinates TZ comments
JP +353916+1394441 Asia/Tokyo
coordinates
というのは緯度経度のことです。日本標準時は東経135度の子午線がちょうど兵庫県を通っているため、協定世界時 (UTC) に135度分のオフセット (+0900) を加えたものになります。それはさておき。
もうちょっと見てみましょう。日時のフォーマットは
format()
で変更できるようです。>>> cals.events[5].begin.format('YYYY/MM/DD HH:mm:ss')
'2008/12/10 00:00:00'
>>> local.format('YYYY/MM/DD HH:mm:ss')
'2008/12/10 09:00:00'
>>> cals.events[5].begin.to('Asia/Tokyo').format('YYYY/MM/DD HH:mm:ss')
'2008/12/10 09:00:00'
これなら読みやすくなりそうです。
ということで試しに書いてみました。
for i in range(0, len(cals.events)):
with cals.events[i] as ev:
print('{0}, {1}, {2}, {3}, {4}'.format(
ev.begin.to('Asia/Tokyo').format('YYYY/MM/DD HH:mm:ss'),
ev.end.to('Asia/Tokyo').format('YYYY/MM/DD HH:mm:ss'),
ev.summary,
ev.location,
ev.description,
))
実行してみると、AttributeError: __enter__
というエラーが返ってきました。>>> import ics
>>> dir(ics.Calendar.events)
['__class__', '__delattr__', '__delete__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__isabstractmethod__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__set__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'deleter', 'fdel', 'fget', 'fset', 'getter', 'setter']
with
文で使用するには __enter__
と __exit__
が必要なので、events
ではwith
文は使えないようです。結局、試行錯誤しながら以下のようにしてみました。
import ics
import re
with open('diary.ics', encoding = 'utf-8') as fin:
cals = ics.Calendar(fin.read())
with open('output.csv', 'w', encoding = 'utf-8') as fout:
fout.write('開始, 終了, 件名, 場所, 説明\n')
for i in range(0, len(cals.events)):
s = u'{0}, {1}, "{2}", "{3}", "{4}"'.format(
cals.events[i].begin.to('Asia/Tokyo').format('YYYY/MM/DD HH:mm:ss'),
cals.events[i].end.to('Asia/Tokyo').format('YYYY/MM/DD HH:mm:ss'),
cals.events[i].name,
cals.events[i].location,
cals.events[i].description,
)
if re.search('(東京)|(岡山)|(藤沢)', s):
if not re.search('移動', s):
fout.write(s + '\n')
これで「東京」「岡山」「藤沢」を含み、かつ「移動」を含まないものをファイルに書き出します。ファイルは
with
文で扱っているので、ブロック終了時に自動的に close()
されますから fout.close()
はありません。
0 件のコメント:
コメントを投稿