BREW スケジューラー 〜 BREW C++ vCalendar プログラミング 〜
vCalendar とは
vCalendar は、異なるスケジューラーアプリ間でデータをインポートやエクスポートするための、カレンダー情報に関する標準フォーマットです。
関連情報 : vCard and vCalendar
関連情報 : VCalendar - Wikipedia / 関連情報 : ICalendar - Wikipedia
vCalendar のフォーマット
vCalendar データの基本フォーマットは次の通りです。
BEGIN:VCALENDAR VERSION:1.0 BEGIN:VEVENT SUMMARY:meeting DTSTART:20050324T113450Z DTEND:20050324T120000Z LAST-MODIFIED:20050717T005300Z END:VEVENT END:VCALENDAR
- vCalendar データは "BEGIN:VCALENDAR" で始まり、"END:VCALENDAR" で終わります。
- 各行は"項目名:値" の形式となっています。
- "SUMMARY:" はスケジュールの内容を表します。
- "DTSTART:" は開始時刻、 "DTEND:" は終了時刻、"LAST-MODIFIED:" はデータの最終更新時刻です。
- 時刻のフォーマットは "20050324T113450Z" 形式で表現します。これは "2005年3月24日11時34分50秒" を意味します。
本アプリでは vCalendar データを VCalendar クラスで処理します。
class VCalendar { private: SFXAnsiString _version; // VERSION: SFXDate _startDT; // DTSTART: SFXDate _endDT; // DTEND: SFXDate _lastModifiedDT; // LAST-MODIFIED: SFXAnsiString _summary; // SUMMARY: SFXAnsiString _others; // その他 public: //以下、メンバ関数 };
日付データは SFXDate クラスを使います。
_others には、このアプリで使わないデータを格納します。
vCalendar フォーマットの解析
Import() は vCalendar データを VCalendar クラスに取り込むための関数、Export() は VCalendar クラスから vCalendar データを書き出すための関数です。
Void Import(SFXAnsiStringConstRef str); Void Export(SFXAnsiStringPtr str);
Import 関数の引数に vCalendar 形式のテキストデータを SFXAnsiString 文字列として渡すことで、メンバ変数に値を設定します。
Export 関数は VCalendar クラスのメンバ変数の値を vCalendar 形式のデータとして書き出します。
※ Import 関数、Export 関数では、文字列コピーのオーバーヘッドは起きません。
Import 関数の実装
- 最初の行が "BEGIN:VCALENDAR" であるかチェックする
- 3. 4. の処理を各行について実行する
- 一行の文字列をコロン ':' の左側 ( field ) と右側 ( value ) に分ける
- field の値に対応するメンバ変数に value の値を代入する
_startDate、endDate、_lastModifiedDate は 日付 ( SFXDate ) のインスタンス変数です。Parse 関数は文字列の日付を解析して SFXDate オブジェクトに変換します。
// vCalendar形式の文字列を取り込む Void VCalendar::Import(SFXAnsiStringConstRef string) { SInt32 c1, c2; SFXAnsiStringConst format("YYYYMMDD%Thhmmss"); SFXAnsiString field, value; _others.Clear(); // BEGIN:VCALENDARが最初に存在しなければエラー c1 = string.IndexOf("BEGIN:VCALENDAR"); if (c1 < 0) { c1 = string.IndexOf("begin:vcalendar"); if (c1 < 0) { return; } } c2 = string.IndexOf('\n', c1); while (true) { c1 = string.IndexOf(':', c2); // 次のコロンを探す if (c1 < 0) { // 見つからないなら break; // 終了 } // ****:**** のコロンの左側を取得して、文字の後ろの空白文字はカット field = string.Substring(c2 + 1, c1).Trim(); c2 = string.IndexOf('\n', c1); // 次の行末を探す if (c2 < 0) { // 見つからないなら c2 = string.GetLength(); // 文字列の最後尾とする } // ****:**** のコロンの右側を取得して、文字の後ろの空白文字はカット value = string.Substring(c1 + 1, c2).Trim(); if (field.Equals("begin", false)) { // ; // } else if (field.Equals("end", false)){ if (value.Equals("vcalendar"), false) { break; // END:VCALENDARのとき、終了 } // } else if (field.Equals("version", false)) { // バージョン _version = value; } else if (field.Equals("dtstart", false)) { // 開始時刻 _startDate.Parse(format, value); // 時刻を解析して設定 } else if (field.Equals("dtend", false)) { // 終了時刻 _endDate.Parse(format, value); // 時刻を解析して設定 } else if (field.Equals("last-modified", false)) { // 更新時刻 _lastModifiedDate.Parse(format, value); // 時刻を解析して設定 // イベントデータ } else if (field.Substring(0, 7).Equals("summary", false)) { _summary = value; } else { // その他のデータ _others << field << ":" << value << "\r\n"; } } return; }
Export 関数の実装
// vCalendar形式のデータを書き出す Void VCalendar::Export(SFXAnsiStringPtr string) const { SFXAnsiString format("YYYYMMDD%Thhmmss%Z"); string->Set("BEGIN:VCALENDAR\r\nVERSION:"); *string += _version; *string += "\r\nBEGIN:VEVENT\r\nCLASS:PUBLIC\r\nDTSTART:"; *string += _startDate.Format(format); *string += "\r\nDTEND:"; *string += _endDate.Format(format); *string += "\r\nSUMMARY;ENCODING=QUOTED-PRINTABLE:"; *string += _summary; *string += "\r\nLAST-MODIFIED:"; *string += _lastModifiedDate.Format(format); *string += "\r\n"; *string += _others; *string += "END:VEVENT\r\nEND:VCALENDAR\r\n"; return; }
文字列を += 演算子で末尾に追加しています。
SFXDate クラスの Format 関数は Parse 関数の逆で、 SFXDate オブジェクトを文字列の日付に変換します。