VCalendar

**iCalendar** 是「日曆數據交換」的標準（RFC 5545）。
此標準有時指的是「iCal」，即蘋果公司的出品的一款同名日曆軟體（見 iCal），這個軟體也是此標準的一種實現方式。

iCalendar 允許使用者通過電子郵件的方式發送「會議請求」或「任務」。收信人使用支援 iCalendar 郵件客戶端，便可以很方便地回應發件人，接受請求或另外提議一個新的會議時間。

iCalendar 已得到很多產品的支援。通常情況下，iCalendar 數據是使用電子郵件交換，但它也可以獨立使用，而不局限於某種傳輸協定。例如，可以通過 WebDav 伺服器或 SyncML 來進行共享與修改。簡單的網頁伺服器（只使用 HTTP 協定）也常常被用來分發公共事件的 iCalendar 數據，或發佈個人的時間謀劃安排。發佈者可以使用 hCalendar 把 iCalendar 數據嵌入到網頁中。（hCalendar 是一種通過（X）HTML 來表現 iCalendar 的微格式）

## 歷史與設計

iCalendar 是由網際網路工程任務組的日曆與計劃工作組設計（OpenText 公司的 Anik Ganguly 主導），並由蓮花公司的 Frank Dawson 和微軟的 Derik Stenerson 發表。iCalendar 本身是基於網際網路郵件協會（IMC）的 vCalendar 開發設計而來的。它通常是以檔名後綴為.ics 或.ifb 的文字檔案儲存的。現有標準是於 2009 年九月發布的 RFC 5545，上一個標準是 RFC 2445 （頁面存檔備份，存於網際網路檔案館）。

以.ics 為後綴名的檔案（在 Apple Mac 系統中使用 "iCal" 類型代碼），表示該檔案包含了日曆和計劃資訊。而以.ifb 為後綴名的檔案（在 Apple Mac 系統中使用 "iFBf" 類型代碼），表示該檔案包含 了空閒和忙碌時間資訊。

通常 iCalendar 使用 UTF-8 字元編碼；但也可以使用 MIME 中的 charset 參數來指其它的字元編碼（如果它的傳送協定支援 MIME 的話）。

在 iCalendar 檔案中，每一行必須以 CR+LF（十六進制代碼為 0D0A）為結尾。每一行不得超過 75 位元組 / 八位元組。如果一行數據長於這個限制，則必須換行；後面一行使用空格符（十六進制代碼為 20）或者制表符（十六進制代碼為 09）作開始，以表示本行內容是上面一行內容的繼續。內容數據中的換行符，可以反斜槓符 '/' 後跟數字（UTF-8 中為 5C 6E 或 5C 4E）來表示。

iCalendar 的 MIME 類型被定義為 _text/calendar_。

## 局限和發展

iCalendar 格式只是被設計用來傳送日曆和計劃表數據，如事件；而故意沒有定義操作這些數據的行為。因為，在編寫程式時需要協商如何操作它們。

iCalendar 本意是提供一種公共格式來定義開放的網際網路可交換的日曆和計劃表數據。當這些特性被廣泛支援應用後，很多效能問題逐漸顯現出來了。比如，大多數應用都不支援旅行（VJOURNAL）。"在標準中，循環重復的會議有一些含糊不清，這導致在現有不同的應用之間仍然無法真正地互動。"

iCalendar 中的日曆無法相容非格里高利曆，比如以色列的希伯來曆和沙烏地阿拉伯的伊斯曆都是陰曆。

「日曆存取協定」備忘錄（RFC 4324 （頁面存檔備份，存於網際網路檔案館））首次嘗試建立一個統一的建立實時日曆系統。可能是因為過於複雜，這個協定最終被放棄了。

無論如何，像 GroupDav 和 CalDAV 這些基於 iCalendar 的協定已經越來越廣泛地應用在客戶端和伺服器端軟體包中了。

網際網路工程任務組的日曆與計劃工作組 已經提交了關於 iCalendar 標準的附加修改提案。但這個工作組於 2011 年一月份被解散了。他們大部分工作重心轉移到了前一個標準的條款解釋。而後續的創新工作由日曆和計劃協會（簡稱為 Calconnect）來完成。

## 技術標準

### 核心物件

iCalendar 中的頂級元素是日曆和計劃核心物件，一組日曆和計劃資訊。通常情況下，這些資訊應該只包含單一的 iCalendar 物件。但可以聲明一個組包含多個 iCalendar 物件。

第一行必須是 "BEGIN:VCALENDER"，最後一行必須是 "END:VCALENDER"；兩行之間數據稱之為 "icalbody"。

icalbody 由一系列日曆屬性和一個以上的日曆組件組成。日曆屬性被應用於整個日曆。日曆組件則是由若干日曆屬性描述成的一個日曆語義。比如，日曆組件可以指定一個事件、一個待辦事項列表、一個旅行事項、時區資訊、繁忙 / 空閒時間資訊，或者一個警報。在許多協定實現（比如 Google Calendar）中不允許出現空行。

下在是一個簡單的 iCalendar 物件範例，它描述了法國國慶日，即從 1997 年七月 14 日 17:00 到 1997 年七月 15 日 03:59:59 的巴士底日。

```
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
UID:uid1@example.com
DTSTAMP:19970714T170000Z
ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
DTSTART:19970714T170000Z
DTEND:19970715T035959Z
SUMMARY:Bastille Day Party
END:VEVENT
END:VCALENDAR
```

### 事件（VEVENT）

VEVENT 描述一個事件，在日曆上一系列計劃好的時間點。通常，當使用者接受一個日曆事件，這將導致在那個時間裡，使用者被認為是忙碌的。VEVENT 可以包含一個 VALARM 物件來允許一個警報。事件應該有一個 DTSTART 來描述事件的開始時間，和一個 DTEND 來描述事件的結束時間。如果事件是循環的，則 DTSTART 應該設定第一個事件的開始時間。

VEVENT 同樣可以應用在沒有特定時間的日曆事件上，比如周年紀念日、每日提醒。

如果你需要發送取消事件的請求。那麼在請求中事件組件中，UID 屬性應該與原事件一致並且，下面這些屬性應該設定成 cancel。

```
METHOD:CANCEL
STATUS:CANCELLED
```

為了發送事件的更新請求，除了設定 UID 和其它更新屬性值外。還需要設定新序列值

```
SEQUENCE:<新序列值>
```

比如，第一個更新版本

```
SEQUENCE:1
```

在 Microsoft Outlook 中，SUMMARY 屬性應當與 "Appointment" 中的 "Subject" 項一致，DESCRIPTION 屬性緊跟著 SUBJECT 屬性。另外，Outlook 2003 要求指定 UID 和 DTSTAMP 屬性。

### 待辦事項（VTODO）

VTODO 描述一條待辦事項。

下面的例子描述了一個應於 1998 年四月 15 日的待辦事項。屆時一個響鈴將會響起。在待辦事項完成前，將會一小時提醒一次，共提醒四次。SEQUENCE 屬性顯示這條提醒在建立之後，還被修改了兩次。

```
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//ABC Corporation//NONSGML My Product//EN
BEGIN:VTODO
DTSTAMP:19980130T134500Z
SEQUENCE:2
UID:uid4@host1.com
ACTION:AUDIO
TRIGGER:19980403T120000
ATTACH;FMTTYPE=audio/basic:http://example.com/pub/audio-
    files/ssbanner.aud
REPEAT:4
DURATION:PT1H
END:VTODO
END:VCALENDAR
```

### 旅行事項（VJOURNAL）

VJOURNAL 是一個旅行事項。它們將一段描述文字關聯一個詳細的日曆日期上，這可以被使用者記錄活動和成長日誌，或者描述待辦事項的進展。VJOURNAL 日曆組件不會影響日曆上的時間狀況，所以不會對空閒和繁忙狀態有任何影響。在實踐上，有很少的程式支援 VJOURNAL 項，不過也有存在一些實現。比如：Plum Canary's Chirp 軟體將 VJOURNAL 和 VTODO 一起使用。KDE 中的 KOrganizer 也支援 VJOURNAL。

下面就是旅行事項的例子

```
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//ABC Corporation//NONSGML My Product//EN
BEGIN:VJOURNAL
DTSTAMP:19970324T120000Z
UID:uid5@host1.com
ORGANIZER:MAILTO:jsmith@example.com
STATUS:DRAFT
CLASS:PUBLIC
CATEGORIES:Project Report, XYZ, Weekly Meeting
DESCRIPTION:Project xyz Review Meeting Minutes\n
    Agenda\n1. Review of project version 1.0 requirements.\n2.
    Definition
    of project processes.\n3. Review of project schedule.\n
     Participants: John Smith, Jane Doe, Jim Dandy\n-It was
      decided that the requirements need to be signed off by
      product marketing.\n-Project processes were accepted.\n
     -Project schedule needs to account for scheduled holidays
      and employee vacation time. Check with HR for specific
      dates.\n-New schedule will be distributed by Friday.\n-
     Next weeks meeting is cancelled. No meeting until 3/23.
END:VJOURNAL
END:VCALENDAR
```

**注意**: 這個例子中來自於 RFC 2445 （頁面存檔備份，存於網際網路檔案館）。在這裡將原文中的 CATEGORY 修正為 CATEGORIES，這是原文中的一個錯誤。

### 空閒 / 繁忙時間（VFREEBUSY）

VFREEBUSY 被用在 空閒 / 繁忙時間 設定請求，這種請求的回應，以及繁忙時間的發布中。
下面就是一個系統時間發布的例子。

```
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//RDU Software//NONSGML HandCal//EN
BEGIN:VFREEBUSY
ORGANIZER:MAILTO:jsmith@example.com
DTSTART:19980313T141711Z
DTEND:19980410T141711Z
FREEBUSY:19980314T233000Z/19980315T003000Z
FREEBUSY:19980316T153000Z/19980316T163000Z
FREEBUSY:19980318T030000Z/19980318T040000Z
URL:http://www.example.com/calendar/busytime/jsmith.ifb
END:VFREEBUSY
END:VCALENDAR
```

### 其它組件類型

其它組件類型還有 **VTIMEZONE**（時區）和 **VALARM**（警報）。還有一些組件允許包含其它組件（VALARM 通常被包含於其它組件）。

### 發布更新

當計劃事件更改，UID 欄位將發布更新。首先事件建立時會生成一個全域唯一識別碼作為 UID。之後當有一個事件跟隨這個 UID 發布，則認為這是早先事件的修改版本，並替換掉它。

### 日曆擴充

iCalendar 支援私有擴充，即在屬性名前冠以 "X-" 字首。

比如：

* X-RECURRENCE-ID
* X-EPOCAGENDAENTRYTYPE
* X-FUNAMBOL-AALARMOPTIONS
* X-FUNAMBOL-ALLDAY
* X-MICROSOFT-CDO-ALLDAYEVENT
* X-MICROSOFT-CDO-BUSYSTATUS
* X-WR-CALNAME
* X-WR-CALDESC
* X-WR-RELCALID
* X-WR-TIMEZONE
* X-PUBLISHED-TTL