概要
この記事ではiCalendarデータの基本的な仕様およびPythonでiCalendarデータを扱えるicalendarパッケージについてまとめます。
iCalendarとは
iCalendarとはインターネットを通してPCやスマートフォンなど異なるデバイス間でカレンダー情報をやりとりするためのデータ形式です。
現在、カレンダー情報を扱うためのもっとも標準的な形式であり、iCalendar形式で作成されたファイルの拡張子は通常.ics
、.ical
、.icalendar
のいずれかになります。
なおiCalendarではTODO情報やジャーナル情報も取り扱うことが可能ですが、それらについての説明は割愛します。
iCalendarの歴史
iCalendarは、1998年にIETF(Internet Engineering Task Forceの略。インターネット技術の標準化推進団体)によってRFC2445が作成され、以来、標準仕様とされてきました。
その後、インターネット技術の発展に合わせて、2009年には大きな改訂を加えたRFC5545が策定され、RFC5545の拡張的役割で2016年にRFC7986が定義されました。
より詳しい歴史を知りたい場合はこちらの記事(英語)が参考になります。
https://devguide.calconnect.org/iCalendar-Topics/History/
iCalendarデータ形式の構造
iCalendarデータの例
Googleカレンダーをエクスポートすると入手できるicsファイルのデータを例として、iCalendarデータの形式について説明します。
まず画像のような設定で予定を作成しました。
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:iCalendarテスト
X-WR-TIMEZONE:UTC
BEGIN:VEVENT
DTSTART:20210918T000000Z
DTEND:20210918T010000Z
DTSTAMP:20210917T064347Z
ORGANIZER:mailto:test-organizar@example.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=:test@example.com
il.com;X-NUM-GUESTS=0:mailto:test@example.com
il.com
CREATED:20210917T064324Z
DESCRIPTION:Googleカレンダーのicsファイルを見る
LAST-MODIFIED:20210917T064324Z
LOCATION:自宅
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:テスト用の予定
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
データ構造と各セクション
上記のデータを見るとわかる通り、iCalendarは全体をBEGIN:VCALENDAR
とEND:VCALENDAR
で囲み、その中に各プロパティを記述します。
VCALENDAR
セクション内にはBEGIN:VEVENT
とEND:VEVENT
に囲まれたセクションがあり、ここにはカレンダーの各予定(イベント)ごとの情報が定義されます。
VCALENDAR
は一度だけしか登場しませんが、VEVENT
はカレンダーに登録されたイベントの数だけ設定されます。
次にiCalendarの具体的なプロパティについて説明します。
VCALENDARのプロパティ
プロパティ名 | 役割 |
---|---|
PRODID | カレンダーの識別子 |
VERSION | iCalendarデータを生成したアプリケーションの識別情報。サービス名や利用言語情報を組み合わせるケースが多い |
CALSCALE | カレンダーの暦法。一般的にGREGORIANを指定する |
METHOD | PUBLISH・REQUEST・CANCELなどの値が入る |
VEVENTのプロパティ
プロパティ名 | 内容 |
---|---|
DTSTART | イベント開始日時 |
DTEND | イベント終了日時 |
DTSTAMP | iCalendarオブジェクトのインスタンスが作成された日時 |
ORGANIZER | イベント主催者情報。詳しくはこちら |
ATTENDEE | イベント参加者情報。詳しくはこちら |
CREATED | イベントが作成された日時 |
DESCRIPTION | イベントの説明文 |
LOCATION | イベント開催地 |
SEQUENCE | イベント情報を変更する度に更新されていくシーケンス番号 |
STATUS | イベントの状態。一般的にイベント作成時はCONFIRMED、キャンセル時はCANCELLEDが指定される |
SUMMARY | イベントタイトル |
TRANSP | イベントを設定した時間の状態。OPAQUEまたはTRANSPARENTという値が入る。TRANSPARENTは空き時間を表すため、会議などの予定の場合OPAQUEを設定する |
ORGANIZER・ATTENDEEの詳細
ORGANIZER(主催者情報)とATTENDEE(参加者情報)ではカレンダー上での表示名や出欠の返事を求めるかなど細かな設定ができます。
ORGANIZER;CN=テスト太郎:mailto:test_organizer@example.com
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=テスト花子:mailto:test@example.com
例えば上記のような設定の場合、イベントの主催者はtest_organizer@example.com
でカレンダー上ではテスト太郎と表示されます。
参加者はtest@example.com
で表示名はテスト花子、イベントには必須参加であり、参加状況についてアクションを求めるということになります。
プロパティ名 | 内容 |
---|---|
CN | カレンダーにおける表示名 |
ROLE | 役割。CHAIR(議長)・REQ-PARTICIPANT(必須参加)・OPT-PARTICIPANT(任意参加)などが設定される |
PARTSTAT | 参加状況について。NEEDS-ACTION・ACCEPTED・DECLINED・TENTATIVE・DELEGATEDなどが設定される |
PythonでiCalendarデータを扱うには
PythonにはRFC5545互換のiCalendarファイル用パーサジェネレータであるicalendarパッケージがあります。
https://pypi.org/project/icalendar
公式サイトにインストール方法や詳細な使い方が載っているためぜひご覧になってください。
https://icalendar.readthedocs.io/en/latest/
ここではicalendarパッケージの基本的な使い方を紹介します。
icalendarパッケージの使い方
ジェネレータとして
例として「2021年10月1日12時から一時間〇〇会議あり」という予定をicalendarパッケージを利用して作成してみます。
# coding: utf-8
from datetime import datetime
from icalendar import Calendar, Event, vCalAddress, vText
cal = Calendar()
cal.add('prodid', '-//Test//test-product//ja//')
cal.add('version', '2.0')
cal.add('calscale', 'GREGORIAN')
cal.add('method', 'REQUEST')
# イベント作成
event = Event()
event.add('summary', u'〇〇会議')
event.add('dtstart', datetime(2021, 10, 1, 12))
event.add('dtend', datetime(2021, 10, 1, 13))
event.add('description', u'〇〇についての会議です')
# 開催者設定
organizer = vCalAddress('MAILTO:test_organizer@example.com')
organizer.params['cn'] = vText(u'テスト 太郎')
organizer.params['role'] = vText('CHAIR')
event['organizer'] = organizer
# 参加者設定
attendee = vCalAddress('MAILTO:test@example.com')
attendee.params['cn'] = vText('テスト 花子')
attendee.params['ROLE'] = vText('REQ-PARTICIPANT')
event.add('attendee', attendee)
cal.add_component(event)
# icsファイル作成
f = open('test.ics', 'wb')
f.write(cal.to_ical())
f.close()
各プロパティを定義するためにはadd()メソッドを利用します。
このコードを実行すると以下のようなicsファイルが作成されます。
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Test//test-product//ja//
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
SUMMARY:〇〇会議
DTSTART;VALUE=DATE-TIME:20211001T120000
DTEND;VALUE=DATE-TIME:20211001T130000
ATTENDEE;CN="テスト 花子";ROLE=REQ-PARTICIPANT:MAILTO:test@example.com
DESCRIPTION:〇〇についての会議です
ORGANIZER;CN="テスト 太郎";ROLE=CHAIR:MAILTO:test_organizer@example.com
END:VEVENT
END:VCALENDAR
パーサとして
先ほど作成したicsファイルをicalendarパッケージでパースしてみます。
まず、from_ical()メソッドを使い、iCalendarデータをプリミティブなPythonの型にデコードします。
# coding: utf-8
from datetime import datetime
from icalendar import Calendar
file = open('test.ics')
calendar = Calendar.from_ical(file.read())
print(calendar)
> VCALENDAR({u'CALSCALE': vText('GREGORIAN'), u'VERSION': vText('2.0'), u'METHOD': vText('REQUEST'), u'PRODID': vText('-//Test//test-product//ja//')}, VEVENT({u'ATTENDEE': vCalAddress('MAILTO:test@example.com'), u'DESCRIPTION': vText('〇〇についての会議です'), u'DTEND': <icalendar.prop.vDDDTypes object at 0x10b52a2d0>, u'DTSTART': <icalendar.prop.vDDDTypes object at 0x10b694390>, u'ORGANIZER': vCalAddress('MAILTO:test_organizer@example.com'), u'SUMMARY': vText('〇〇会議')}))
walk()メソッドを使うと、各プロパティの値を取り出せます。
print(calendar.walk('VCALENDAR')[0]['VERSION'])
> 2.0
print(calendar.walk('VEVENT')[0]['ORGANIZER'])
> MAILTO:test_organizer@example.com
終わりに
広く普及しているiCalendarですが、なかなかデータの中身をじっくり見る機会はなく、まとめてみると構造はシンプルながらも意外と多様な情報を持っていることに気付かされました。
冒頭で書いた通り、イベント予定の管理以外にTODO情報やジャーナル情報も扱えます。今回は紹介していませんが、それらのためのプロパティも存在するので興味があれば調べてみると面白いかもしれません。
参考サイト
iCalendar関連
https://datatracker.ietf.org/doc/html/rfc2445
https://datatracker.ietf.org/doc/html/rfc5545
https://datatracker.ietf.org/doc/html/rfc7986
https://icalendar.org/
https://devguide.calconnect.org/iCalendar-Topics
icalendarパッケージ関連
https://icalendar.readthedocs.io/en/latest/
https://github.com/collective/icalendar