Pages

2011年6月5日日曜日

iCalendarでgoogleカレンダーへの登録を自動化

会社で使っているグループウエアのスケジュール情報をGoogleカレンダーに写すことを考えてみた。グループウエアにicalファイルを発行する機能があらば良いのだが、あいにくそのような機能はない。
用意するプログラムの概要は
  • 会社のグループウエアのデータベースからsqlでスケジュールファイルを出力
  • スケジュールファイルからicalファイルを作成し、webで公開
  • Googleカレンダーで「その他のカレンダー」を追加。(url指定)

iCalendarは、RFCで定義されている、カレンダー情報の共通規約です。あんまり、普及していないような気もしますが。詳細は定義は、以下が日本語でわかりやすいです。
iCalendar

icalendarを扱うライブラリが、rubygemにありましたので、それをインストールします。
$ sudo gem install icanlendar

sqlで取得したスケジュールファイルはこんな感じ。
ZZZ FW切り替え作業 監視 |       |      | 2011-06-04 00:00:00 | 2011-06-04 00:00:00
月曜ミーティング        |       |      | 2011-06-06 09:00:00 | 2011-06-06 10:00:00

  1. require "rubygems"  
  2. require "icalendar"  
  3. require "kconv"    # 日本語の文字コードを扱うための標準ライブラリ  
  4. require "date"  
  5. # OpenStruct (標準ライブラリ)  
  6. # javascriptのobjectのようにプロパティの追加を気楽に扱う  
  7. # http://memo.yomukaku.net/entries/244  
  8. require "ostruct"   
  9.   
  10. schdule_file = 'schedules.dat'  
  11. schedules = []  
  12. File.readlines(schedule_file).each do |line|  
  13.   v = line.split(/\|/).map{|val| val.strip}  
  14.   next unless v.size > 1  
  15.   schedule = OpenStruct.new  
  16.   schedule.user = v[0]  
  17.   schedule.event = v[1]  
  18.   schedule.content = v[2]  
  19.   schedule.place = v[3]  
  20.   schedule.start = DateTime.parse(v[4])  
  21.   schedule.end = DateTime.parse(v[5])  
  22.   schedules.push schedule  
  23. end  
  24.   
  25. cal = Icalendar::Calendar.new  
  26. # VEVENT コンポーネント  
  27. # ここがスケジュールの本体  
  28. schedules.each do |schedule|  
  29.   cal.event do  
  30.     dtstart schedule.start, {'TZID' => 'Asia/Tokyo'}  
  31.     dtend   schedule.end  , {'TZID' => 'Asia/Tokyo'}  
  32.     summary schedule.event  
  33.     description schedule.content  
  34.   end  
  35. end  
  36.   
  37. # STANDARD コンポーネント  
  38. standard_component = Icalendar::Component.new('STANDARD')  
  39. standard_component.custom_property('dtstart''19700101T000000')  
  40. standard_component.custom_property('tzoffsetfrom''+0900')  
  41. standard_component.custom_property('tzoffsetto''+0900')  
  42. standard_component.custom_property('tzname''JST')  
  43.   
  44. # VTIMEZONE コンポーネント  
  45. vtimezone_component = Icalendar::Component.new('VTIMEZONE')  
  46. vtimezone_component.custom_property('tzid''Asia/Tokyo')  
  47. vtimezone_component.add(standard_component)  
  48. cal.add(vtimezone_component)  
  49.   
  50. # iCalファイル  
  51. ical_file = 'calendar.ics'  
  52. File.open(ical_file, "w+b") { |f|  
  53.     f.write(cal.to_ical.toutf8)  
  54. }  
require "rubygems"
require "icalendar"
require "kconv"    # 日本語の文字コードを扱うための標準ライブラリ
require "date"
# OpenStruct (標準ライブラリ)
# javascriptのobjectのようにプロパティの追加を気楽に扱う
# http://memo.yomukaku.net/entries/244
require "ostruct" 

schdule_file = 'schedules.dat'
schedules = []
File.readlines(schedule_file).each do |line|
  v = line.split(/\|/).map{|val| val.strip}
  next unless v.size > 1
  schedule = OpenStruct.new
  schedule.user = v[0]
  schedule.event = v[1]
  schedule.content = v[2]
  schedule.place = v[3]
  schedule.start = DateTime.parse(v[4])
  schedule.end = DateTime.parse(v[5])
  schedules.push schedule
end

cal = Icalendar::Calendar.new
# VEVENT コンポーネント
# ここがスケジュールの本体
schedules.each do |schedule|
  cal.event do
    dtstart schedule.start, {'TZID' => 'Asia/Tokyo'}
    dtend   schedule.end  , {'TZID' => 'Asia/Tokyo'}
    summary schedule.event
    description schedule.content
  end
end

# STANDARD コンポーネント
standard_component = Icalendar::Component.new('STANDARD')
standard_component.custom_property('dtstart', '19700101T000000')
standard_component.custom_property('tzoffsetfrom', '+0900')
standard_component.custom_property('tzoffsetto', '+0900')
standard_component.custom_property('tzname', 'JST')

# VTIMEZONE コンポーネント
vtimezone_component = Icalendar::Component.new('VTIMEZONE')
vtimezone_component.custom_property('tzid', 'Asia/Tokyo')
vtimezone_component.add(standard_component)
cal.add(vtimezone_component)

# iCalファイル
ical_file = 'calendar.ics'
File.open(ical_file, "w+b") { |f|
    f.write(cal.to_ical.toutf8)
}

さらっと、書いたが実はいろいろと苦労した。
  • 最初はタイムゾーンを設定せずに作成したため、時間がずれた
  • Googleカレンダーの更新が遅いため、ファイルを変更してもカレンダーに反映せず

それにしても、Googleカレンダーはどの程度の間隔で外部カレンダー情報を更新しているのだろうか? サイトを調べた限りでは、数時間ということだが、なんかいつまでたっても更新しない。

困ったもんだ。

0 件のコメント:

コメントを投稿