カレンダーに使われるiCalendar形式について part1

iCalendarファイルはカレンダーなどで予定を読み込んだりする際に用いられる形式です。
予定などを他の人と共有する手段はいくつかありますが、iCalendarファイルを渡して読み込んでもらうことは各人の環境を問わずに行うことができる良い方法だと思います。
そのようなiCalendarファイルについて少し調べてみたので簡単にまとめます。

#iCalendarファイルの特徴

- スケジュールに使われる標準形式
- MIMEタイプは「text/calendar」
- 拡張子として、.icsが用いられる
- 中身はプレーンテキストで、文字コードはutf-8が標準で用いられる

中身はテキストデータなので、テキストエディターで編集して、拡張子をicsにすれば作成できます。
OSによって多少異なりますが、基本的にはiCalendarファイルを開くと標準のカレンダーアプリに予定を登録することができます。

次に、ファイル内容の記述方法について説明します。

#簡単なスケジュール
iCalendarファイルの使用についてはRFC-2445にまとめられています。
この仕様書にあるiCalendarファイルの最もシンプルな例として以下のようなものが挙げられています。

```
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
DTSTART:19970714T170000Z
DTEND:19970715T035959Z
SUMMARY:Bastille Day Party
END:VEVENT
END:VCALENDAR
```

ぱっと見だと何のことかわからないと思いますが、これは「1997年7月14日〜15日にBastille Day Party(パリ祭)」という予定を追加できるファイルです。
実際ファイルをクリックして開くと以下のようにカレンダーに追加されました。

![test-ics.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315273/a52854d8-98a4-0d2d-631d-ad2a8a8cf2da.png)


#基本はHTMLと同じマークアップ形式
さて、先ほどのiCalendarファイルの記述について少し整形してみます。

```
BEGIN:VCALENDAR
	VERSION:2.0
	PRODID:-//hacksw/handcal//NONSGML v1.0//EN
	BEGIN:VEVENT
		DTSTART:19970714T170000Z
		DTEND:19970715T035959Z
		SUMMARY:Bastille Day Party
	END:VEVENT
END:VCALENDAR
```
インデントを使ってみやすくしてみました。実際にはインデントを使うと正しく読み込まれないのでご注意ください。
これを見るとBEGIN:〇〇、END:〇〇という記述に挟まれた領域があるのが分かります。
HTMLと同じようにiCalendarも開始と終了で囲む必要があるのです(〇〇の部分にプロバティ名が入ります)。



一番外側にあるのが、VCALENDARと呼ばれるプロバティです。
これはHTMLでいう\<html>\</html>みたいなものですね。

その直下に、

1. VERSION:2.0
1. PRODID:-//hacksw/handcal//NONSGML v1.0//EN
1. BEGIN:VEVENT → END:VEVENT

とあります。
3のVEVENTは予定の日付や時刻、タイトルなどを入れる根幹となる部分なので、詳細は後に説明します。

1と2はファイルの形式についてまとめたもので、HTMLでいうところのヘッダー情報です。
要素は「プロバティ名：値」で記述されます。

#VERSIONとPRODIDについて
いずれも必須項目です。

VERSIONは.ics形式のバージョンを示しています。RFC-2445で規定されているのは2.0で、基本はこれにしておけばいいみたいです。

PRODIDはファイル作成者についての情報で、要するに誰が作成したか名前を記載できる部分です。
例では「-//hacksw/handcal//NONSGML v1.0//EN」となっていますが、特に決まった形式はないみたいです。
よく用いられるのが「-//会社名//個人名(プロダクト名)//国名」みたいです。誰が作ったかを分かればいいので好きな記述にしましょう。

#VEVENTについて
これが予定の詳細についてまとめた部分です。
BEGIN:VEVENT→END:VEVENTで囲まれた中に詳細が記述されます。
もしも予定を複数読み込みたいときはさらにBEGIN:VEVENT→END:VEVENTを追加していけばいいみたいです。

例では、以下のようなブロバティが出てきました。

- DTSTART:19970714T170000Z
- DTEND:19970715T035959Z
- SUMMARY:Bastille Day Party

何となく察すると思いますが、DTSTART・DTENDがそれぞれ予定の開始・終了の日時を表しており、SUMMARYが予定のタイトルです。
このほかにもよく使われるものにLOCATION・URL・DESCRIPTIONなどのプロパティもあるようで、それぞれ場所・URL・メモの記述を追加できます。

基本的にはどれも任意の文字列でいいのですが、DTSTART・DTENDでの日時の表記は少し特殊なので、説明します。

#DTSTARTとDTENDでの日時表記について
日時の表記はISO-8601の国際表記として定められた形式が用いられており、以下の特徴があります。

- 日付は西暦4桁、月2桁、日2桁の計8桁(yyyymmdd)
- 時刻は時・分・秒をそれぞれ2桁ずつで計6桁(hhmmss)
- 日付と時刻の間に「T」を表記
- 末尾の「Z」は協定世界時(UTC)を表す

つまり、例のDTSTARTで書かれている19970714T170000Zは「UTCで1997年7月14日17時00分00秒」を表しているのです。
UTCは経度0度における時間のことで、日本(東経135度)の標準時(JST)は9時間進んでいます。
先ほどの画像を見返すと、Macのカレンダーに登録した際も、ちゃんと9時間ずれの日本時間に直されていることがわかります。

#タイムゾーンについて
ところで、日本にいるのに9時間差の日時を記入するのも、面倒だと思います。
グローバルな予定ならともかく大体は日本にいる人と予定を共有することがほとんどでしょう。
そういう場合には日時のタイムゾーンを以下のように設定できます。

```
DTSTART;TZID=Asia/Tokyo:20180514T200000
```

DTASTARTやDTENDなどの時刻を記入するプロパティにセミコロン(;)を入れ、TZID=(地域名)を追加すします。今回は「Asia/Tokyo」にしましたが、「Japan」などでも読み込まれます。
最後にUTCを表す末尾の「Z」を消せばTZIDで設定した地域のタイムゾーンで読み込まれます。

#終わりに
今回の内容はiCalendarファイルの最低限の機能だけです。
カレンダーアプリで用いられる機能としては、繰り返しや予定時刻のアラート機能など様々なものがあります。
[part2](https://qiita.com/TomOse/items/09864919de266697c760)ではアラーム機能について調べてまとめてみます。

長文・駄文でしたが、ここまで読んでいただきありがとうございました:blush:

#参考にした記事
[iCalendar - Wikipedia](https://ja.wikipedia.org/wiki/ICalendar#コア・オブジェクト)
[RFC-2445](http://www.asahi-net.or.jp/~CI5M-NMR/iCal/rfc2445.txt)