2016年12月13日火曜日

iCalendar形式 技術情報メモ

■ 1. はじめに
iCalendar[1]は予定情報を表現・交換するための仕様である。
iCalendarのデータ形式(以下、iCalendar形式)は、Googleカレンダー、Microsoft (Outlook.com)のカレンダーなどのクラウドサービスや、Mozilla Thunderbird、Microsoft Outlookなどのアプリケーションで使用することができる。
iCalendar形式では行事日程のほかにもTo-Do項目や日誌を表現することができるが、ここでは行事日程のみを扱うことにして、今回開発した行事日程カレンダーシステムおよびこれと連動する各種のクラウドサービスやアプリケーション(以下、カレンダーシステム)に関連して使用した事項もしくは使用を検討した事項を記載する。

■ 2. iCalendar形式
◆ 2.1 iCalendar形式の書式
iCalendar形式データの文字エンコーディングはUTF-8である。
また、行末の改行コードはCR LF(16進数で0D 0A)である。例えば、PHPで行を出力するときには次のように行末に \r\n を付さなくてはならない。

 echo "BEGIN:VCALENDAR\r\n";

1行の長さの上限は改行コードを除いて75バイトである。絶対ではないらしい。
それより長くなるときにはルールに従って分割すること。絶対ではないらしい。

◆ 2.2 iCalendarオブジェクト
典型的にはデータ全体のひとまとまりが1個のiCalendarオブジェクトである。
複数が連なっていてもいいが、各種カレンダーシステムの出力を見る限り通常は1個だけからなる。
iCalendarオブジェクトの先頭行と最終行には対応するBEGINとENDがあり、その間には本体がある。
本体はプロパティとコンポーネントからなる。
すなわち、iCalendar形式データの体裁は次の通りである。

 BEGIN:VCALENDAR
 プロパティ
 プロパティ
 ...
 コンポーネント
 コンポーネント
 ...
 END:VCALENDAR

◆ 2.3 iCalendarオブジェクトのプロパティ
次のプロパティは必須である。

・PRODID ... iCalendarオブジェクトを生成した製品のID。
・VERSION ... RFC 5545に従うときには2.0とする。

次のプロパティは1回まで現れることができる。

・CALSCALE ... 通常GREGORIANにする。既定値はGREGORIANなので省略してよい。
・METHOD ... 正直よくわからないがPUBLISHにしておく。

なお、METHODがある場合とない場合とでは、後述のDTSTAMPの解釈が変わる。

この他にRFC 5545で決められていないプロパティとして次のプロパティがある。
これらを認識するかどうかはカレンダーシステムによって異なる。

・X-WR-CALNAME ... カレンダー名。Googleカレンダーでは認識してくれる。
・X-WR-CALDESC ... カレンダーの説明。Googleカレンダーでは認識してくれる。
・X-WR-TIMEZONE ... タイムゾーン。日本ならTokyo/Asiaにしておく。

◆ 2.4 イベントコンポーネント
行事日程を表現するためにはイベントコンポーネントを用いる。
コンポーネント名はVEVENTである。
コンポーネントの先頭行と最終行には対応するBEGINとENDがあり、その間にはプロパティがある。
すなわち、イベントコンポーネントの体裁は次の通りである。

 BEGIN:VEVENT
 プロパティ
 プロパティ
 ...
 END:VEVENT

◆ 2.5 イベントコンポーネントのプロパティ
次のプロパティは必須である。詳細は2.6, 2.7で述べる。

・DTSTAMP ... 前述のMETHODがある場合、iCalendarオブジェクトが生成された日時。
・UID ... イベントに固有のID。絶対の他のイベントとかぶらないようにすること。
・DTSTART ... イベントの開始日時もしくは開始日。

次のプロパティはどちらか片方が1回まで現れることができる。詳細は2.6で述べる。

・DTEND ... イベントの終了日時もしくは終了日。
・DURATION ... イベントの所要時間。

次のプロパティは1回まで現れることができる。
このうちSTATUSとTRANSPについては2.8, 2.9で述べる。

・SUMMARY ... イベントの概要、件名。各種カレンダーシステムで扱われる件名にあたる。
・LOCATION ... イベントの場所。
・STATUS ... イベントの状態。
・TRANSP ... 空き時間検索用の属性。既定値はOPAQUE(予定あり)。
・CREATED ... コンポーネントの作成日時。無くても困らない。
・LAST-MODIFIED ... コンポーネントの更新日時。無くても困らない。
・SEQUENCE ... コンポーネントのリビジョン番号。無くても困らない。

◆ 2.6 日時に関するプロパティ
DTSTAMP, DTSTART, DTENDは日時を示すためのプロパティである。
また、DURATIONは所要時間を示すためのプロパティである。

★値の書式
日時はUTCを次のような書式で記述する。
この例はUTCの2016/09/15 12:30:00(日本時間の2016/09/15 21:30:00)を示す。

 DTSTAMP:20160915T123000

また、時・分・秒の情報が無い日だけの値は次のような書式で記述する。
この例は2016/09/15を示す。セミコロンとコロンの区別に注意すること。

 DTSTART;VALUE=DATE:20160915

なお、ある一日がいつ始まっていつ終わるかはタイムゾーンによって異なるので、この日だけの書式を用いた場合にはタイムゾーンによって開始・終了時刻の解釈が変わることになる。ある一日の開始・終了時刻を特に明示したい場合には時・分・秒の情報を含む書式のほうを使う必要がある。

★DTSTAMP
DTSTAMPの値は日時である。
その解釈はiCalendarオブジェクトのプロパティのMETHODがあるかないかで変わる。

・METHODがある場合、DTSTAMPはiCalendarオブジェクトが生成された日時を指す。
・METHODがない場合、DTSTAMPはLAST-MODIFIEDと同じである。

カレンダーシステムが外部から要求されてiCalendar形式のデータを出力して、iCalendarオブジェクトにMETHOD:PUBLISHというプロパティを付けるのであれば、イベントコンポーネントのDTSTAMPの値はその出力を行った日時になる。

★DSTART, DTEND
DTSTARTの値は日時ないし日であり、イベントの開始日時ないし開始日を示す。
一方、DTENDの値も日時ないし日であり、イベントの終了日時ないし終了日を示す。
DTSTARTの値が日時であればDTENDの値も日時でなくてはならない。
また、DTSTARTの値が日であればDTENDの値も日でなくてはならない。

次の場合について考えるなら
・開始時刻がUTCの2016/09/15 01:30:00(日本時間の2016/09/15 10:30:00)
・終了時刻がUTCの2016/09/15 03:30:00(日本時間の2016/09/15 12:30:00)
DTSTARTとDTENDは次のように記述する。

 DTSTART:20160915T013000
 DTEND:20160915T033000

また、2016/09/15の終日についてはDTSTARTとDTENDは次のように記述する。

 DTSTART;VALUE=DATE:20160915
 DTEND;VALUE=DATE:20160916

DTSTARTのみあってDTEND(および後述のDURATION)が省略された場合、DTSTARTの値の型によって次のように解釈される。

・DTSTARTの値が日時であればDTENDもその日時である(イベントは一瞬)。
・DTSTARTの値が日であれば終日である。

★DURATION
DURATIONは所要時間を示す。値の書式については省略する。
一つのイベントコンポーネントにDTENDとDURATIONの両方ともがあってはならない。

◆ 2.7 UID
UIDはイベントに固有のIDを示す。
全てのカレンダーデータを通じて固有でなくてはならない。
お勧めの方法は、日時・件名から作ったIDに組織のドメイン名を付すことである。

 UID:20160915T013000-hogehogehoge@our.univ.ac.jp

PHPで生成するときには件名から関数md5でハッシュ値(32バイト)を生成し、これを上の例のhogehogehogeの部分に入れればよい。

◆ 2.8 STATUS
STATUSはイベントの状態を示す。
STATUSの値はTENTATIVE, CONFIRMED, CANCELLEDのいずれかである。

・TENTATIVE ... 暫定的。
・CONFIRMED ... 承認済み。決定。
・CANCELLED ... 取消済み。

STATUSが省略された場合の既定値に関する記述はRFC 5545に見当たらない。
試した限りでは、どのカレンダーシステムでSTATUSの省略には特に問題は無かった。

◆ 2.9 TRANSP
TRANSPは空き時間検索のときに参照される属性である。
TRANSPの値はOPAQUE, TRANSPARENTのいずれかである。

・OPAQUE ... 予定ありと見なされる。
・TRANSPARENT ... 検索処理においては無視される。

TRANSPが省略された場合の既定値はOPAQUEである。

◆ 2.10 iCalendarオブジェクトの例
次の例では一つのiCalendarオブジェクトにイベントコンポーネントが二つ含まれる。
なお、行事日程の場所情報が欠落しているときにはLOCATIONは含まない。

 BEGIN:VCALENDAR
 PRODID:-//組織名//製品名とバージョン番号//EN
 VERSION:2.0
 CALSCALE:GREGORIAN
 METHOD:PUBLISH
 X-WR-CALNAME:カレンダー名
 X-WR-CALDESC:カレンダーの説明
 X-WR-TIMEZONE:Asia/Tokyo
 BEGIN:VEVENT
 DTSTAMP:20160915T135022Z
 UID:20161119120000-9f8e0c641376258f8eb14b0d33437b2a@our.univ.ac.jp
 DTSTART:20161119T030000Z
 DTEND:20161119T080000Z
 SUMMARY:リクナビ インターンシップLIVE
 LOCATION:福岡市博多区(福岡国際会議場)
 STATUS:CONFIRMED
 TRANSP:TRANSPARENT
 END:VEVENT
 BEGIN:VEVENT
 DTSTAMP:20160915T135022Z
 UID:20161215130000-3f909c83d2ef6febbcab25221a6b9ed2@our.univ.ac.jp
 DTSTART:20161215T040000Z
 DTEND:20161215T051000Z
 SUMMARY:第4回留学生就職ガイダンス
 LOCATION:キャリア支援センター
 STATUS:CONFIRMED
 TRANSP:TRANSPARENT
 END:VEVENT
 END:VCALENDAR

■ 3. iCalendar形式データの交換
◆ 3.1 プロトコル
下記のシステムはiCalendar形式データをサーバからHTTPで転送して読み取ることができる。

・Mozilla Thunderbird (カレンダー機能。元Lightning)
・Microsoft Outlook
・Googleカレンダー
・Microsoftカレンダー/予定表

URLの頭に付くスキームとして http の代わりに webcal が使われることもある。これは正式ではなく暫定的なスキームである[2]。ファイルの中身ではなくURLをプロトコル処理に渡すために使われる[3]。

◆ 3.2 iCalendar形式データの属性
iCalendar形式データのMIMEタイプは text/calendar である。また、文字エンコーディングは UTF-8 である(2.1節を参照)。
したがって、WebアプリケーションからiCalendar形式データをHTTP応答として出力する際には、ヘッダに次のフィールドが無くてはならない。

 Content-Type: text/calendar; charset=UTF-8

例えばPHPスクリプトの場合、データ本体の出力を開始する前に次のようにしてこのヘッダを出力しなくてはならない。

 header('Content-Type: text/calendar; charset=UTF-8');

■ 参考文献
[1] RFC 5545 Internet Calendaring and Scheduling Core Object Specification (iCalendar), (2009).
https://tools.ietf.org/html/rfc5545
[2] Scheme name: webcal, Internet Assignment Numbers Authority (IANA).
http://www.iana.org/assignments/uri-schemes/prov/webcal
[3] Webcal, Wikipedia (en).
https://en.wikipedia.org/wiki/Webcal

0 件のコメント:

コメントを投稿