iCalendar格式中關於RRule的解析和生成

深藍發表於2013-07-04

最近在做一個關於Calendar的專案,相當於Google Calendar或者Outlook中的Calendar。在Calendar的釋出和共享中,使用到了iCalendar,是一種日曆資料交換的標準,具體參見維基百科:http://zh.wikipedia.org/wiki/ICalendar

由於使用C#開發,所以希望能夠找到一個開源或者免費的iCalendar元件,幫助生成.ics格式的檔案。果然有人做了這樣的事情,那就是DDay.iCal,開源地址:http://sourceforge.net/projects/dday-ical/

關於Calendar,普通的事件都好設定,最麻煩的就是迴圈事件。迴圈事件有多個屬性需要設定,還要計算接下來發生的時間,但是在iCalendar標準中,這些迴圈設定,最終都化作為一個RRule格式的字串(關於RRule格式的標準,我們可以參見http://www.kanzaki.com/docs/ical/rrule.html)。

既然是以DDay.iCal來生成ics檔案,那麼想必這個元件也有解析RRule格式和生成RRule格式的方法。下面就說說如果使用DDay.iCal處理RRule。

一、RRule的解析

DDay.iCal中有個RecurrencePattern物件,該物件可以用於描述迴圈設定。該物件在構造時可以傳入RRule字串,然後我們可以使用RecurringComponent物件的GetOccurrences方法獲得迴圈事件在指定時間區間內的發生的時間。

閒話休說,我們看程式碼:

            RecurringComponent recurringComponent = new RecurringComponent();
            RecurrencePattern pattern = new RecurrencePattern("FREQ=WEEKLY;BYDAY=MO");//RRule設定為每週一發生
            recurringComponent.RecurrenceRules.Add(pattern);
            recurringComponent.Start = new iCalDateTime(Convert.ToDateTime("2013-6-1 00:00:00")); //該迴圈事件從6.1開始發生
            var occurrences = recurringComponent.GetOccurrences(
                Convert.ToDateTime("2013-6-30 23:59:59"),
                //我們雖然要取的是7.1號之後的事件,但是這裡不能寫成2013-7-1,因為該函式在計算時是>startTime <=endTime
                Convert.ToDateTime("2013-7-31 23:59:59")); //獲得迴圈事件在7月份發生的具體時間

            foreach (Occurrence occurrence in occurrences)
            {
                DateTime occurrenceTime = occurrence.Period.StartTime.Local;
                Console.WriteLine(occurrenceTime.ToString("yyyy-MM-dd"));
            }

二、RRule的生成

RRule還是通過RecurrencePattern來設定迴圈的屬性,然後使用ToString方法就能夠獲得RRule字串了。

程式碼如下:

RecurrencePattern pattern = new RecurrencePattern();
pattern.ByDay=new List<IWeekDay>(){new WeekDay(DayOfWeek.Sunday)};//每週週日發生
pattern.Frequency=FrequencyType.Weekly;//迴圈週期為周
Console.WriteLine(pattern.ToString());//生成RRule格式的字串
 
RecurringComponent recurringComponent = new RecurringComponent();
recurringComponent.RecurrenceRules.Add(pattern);
recurringComponent.Start = new iCalDateTime(Convert.ToDateTime("2013-6-1 00:00:00")); //該迴圈事件從6.1開始發生
var occurrences = recurringComponent.GetOccurrences(
    Convert.ToDateTime("2013-6-30 23:59:59"),
    //我們雖然要取的是7.1號之後的事件,但是這裡不能寫成2013-7-1,因為該函式在計算時是>startTime <=endTime
    Convert.ToDateTime("2013-7-31 23:59:59")); //獲得迴圈事件在7月份發生的具體時間

foreach (Occurrence occurrence in occurrences)
{
    DateTime occurrenceTime = occurrence.Period.StartTime.Local;
    Console.WriteLine(occurrenceTime.ToString("yyyy-MM-dd"));
}

相關文章