Class GoogleCalendar::Event
In: lib/googlecalendar/event.rb
Parent: Object

Summary

  this class represents an event of a calendar.

How to use this class

  • MAIL: your gmail account.
  • PASS: password for MAIL.
  • FEED: a calendar‘s editable feed url.
    1. your default calendar‘s feed url is defined in Calendar::DEFAULT_CALENDAR_FEED. To get other calendar‘s feed url, read below.
    2. click "Manage Calendars" in Google Calendar.
    3. select a calendar you want to edit.
    4. copy private address of XML.
    5. change the address‘s end into "/private/full". If your calendar‘s private XML address is
             "http://www.google.com/calendar/feeds/XXX@group.calendar.google.com/private-aaaaaa/basic",
      

      the editable feed url is

             "http://www.google.com/calendar/feeds/XXX@group.calendar.google.com/private/full".
      
    6. for detail, See code.google.com/apis/gdata/calendar.html#Visibility.

create new events

   cal = Calendar.new(Service.new(MAIL, PASS), FEED)
   event = cal.create_event
   event.title = "event title"
   event.desc = "event description"
   event.where = "event location"
   event.st = Time.mktime(2006, 9, 21, 01, 0, 0)
   event.en = Time.mktime(2006, 9, 21, 03, 0, 0)
   event.save!

udpate existing events

   cal = Calendar.new(Service.new(MAIL, PASS), FEED)
   event = cal.events[0]
   event.title = "event title"
   event.desc = "event description"
   event.where = "event location"
   event.st = Time.mktime(2006, 9, 21, 01, 0, 0)
   event.en = Time.mktime(2006, 9, 21, 03, 0, 0)
   event.save!

delete events

   cal = Calendar.new(Service.new(MAIL, PASS), FEED)
   event = cal.events[0]
   event.destroy!

create all day events.

   event = cal.create_event
   event.title = "1 days event"
   event.st = Time.mktime(2006, 9, 22)
   event.en = Time.mktime(2006, 9, 23)
   event.allday = true
   event.save!

   event = cal.create_event
   event.title = "2 days event"
   event.st = Time.mktime(2006, 9, 22)
   event.en = Time.mktime(2006, 9, 24)
   event.allday = true
   event.save!

get existint event

   event = Event.get(FEED, Service.new(MAIL, PASS))

TODO

  • this class doesn‘t support recurring event.

Methods

Constants

ATTRIBUTES_MAP = { "title" => { "element" => "title"}, "desc" => { "element" => "content"}, "where" => { "element" => "gd:where", "attribute" => "valueString" }, "st" => { "element" => "gd:when", "attribute" => "startTime", "to_xml" => "time_to_str", "from_xml" => "str_to_time" }, "en" => { "element" => "gd:when", "attribute" => "endTime", "to_xml" => "time_to_str", "from_xml" => "str_to_time" }
SKELTON = <<XML <?xml version='1.0' encoding='UTF-8'?> <entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'> <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category> <title type='text'></title> <content type='text'></content> <gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency> <gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus> </entry> XML

Attributes

allday  [RW] 
desc  [RW] 
en  [RW] 
feed  [RW] 
srv  [RW] 
st  [RW] 
status  [RW] 
title  [RW] 
where  [RW] 
xml  [RW] 

Public Class methods

get event from event feed

[Source]

     # File lib/googlecalendar/event.rb, line 168
168:     def self.get(feed, srv)
169:       ret = srv.query(feed)
170:       raise EventGetFailed, ret.body unless ret.code == "200"
171:       evt = Event.new
172:       evt.srv = srv
173:       evt.load_xml(ret.body)
174:       evt
175:     end

[Source]

     # File lib/googlecalendar/event.rb, line 108
108:     def initialize()
109:       @xml = nil
110:       self.status = :new
111:     end

Public Instance methods

same as destroy! If failed, this method returns false.

[Source]

     # File lib/googlecalendar/event.rb, line 144
144:     def destroy
145:       do_without_exception(:destroy!)
146:     end

delete this event from google calendar server. If failed, this method throws an Exception.

[Source]

     # File lib/googlecalendar/event.rb, line 149
149:     def destroy!
150:       ret = nil
151:       if self.status == :old
152:         ret = @srv.delete(self.feed) 
153:         raise EventDeleteFailed, "Not Deleted" unless ret.code == "200"
154:       else
155:         raise EventDeleteFailed, "Not Saved"
156:       end
157:       status = :deleted
158:     end

load xml into this instance

[Source]

     # File lib/googlecalendar/event.rb, line 114
114:     def load_xml(str)
115:       @xml = REXML::Document.new(str.to_s)
116:       xml_to_instance
117:       self
118:     end

same as save! If failed, this method returns false.

[Source]

     # File lib/googlecalendar/event.rb, line 121
121:     def save
122:       do_without_exception(:save!)
123:     end

save this event into google calendar server. If failed, this method throws an Exception.

[Source]

     # File lib/googlecalendar/event.rb, line 126
126:     def save!
127:       ret = nil
128:       case self.status
129:       when :new
130:         ret = @srv.insert(self.feed, self.to_s)
131:         raise EventInsertFailed, ret.body unless ret.code == "201"
132:       when :old
133:         ret = @srv.update(self.feed, self.to_s)
134:         raise EventUpdateFailed, ret.body unless ret.code == "200"
135:       when :deleted
136:         raise EventDeleteFailed, "already deleted"
137:       else
138:         raise StandardError, "invalid inner status"
139:       end
140:       load_xml(ret.body)
141:     end

retuns this event‘s xml.

[Source]

     # File lib/googlecalendar/event.rb, line 161
161:     def to_s
162:       @xml = REXML::Document.new(SKELTON) if self.status == :new
163:       instance_to_xml
164:       @xml.to_s
165:     end

Private Instance methods

[Source]

     # File lib/googlecalendar/event.rb, line 178
178:     def do_without_exception(method)
179:       ret = true
180:       begin
181:         self.send(method)
182:       rescue
183:         ret = false
184:       end
185:       ret
186:     end

set attributes of an instance into xml

[Source]

     # File lib/googlecalendar/event.rb, line 206
206:     def instance_to_xml
207:       ATTRIBUTES_MAP.each do |name, hash|
208:         elem = @xml.root.elements[hash["element"]]
209:         elem = @xml.root.elements.add(hash["element"]) if elem.nil?
210:         val = self.send(name)
211:         val = self.send(hash["to_xml"], val) if hash.has_key?("to_xml")
212:         if hash.has_key?("attribute")
213:           elem.attributes[hash["attribute"]] = val
214:         else
215:           elem.text = val
216:         end
217:       end
218:     end

Allday Event Bugs

When creating all day event, the format of gd:when startTime and gd:when endTime must be "yyyy-mm-ddZ" which represents UTC. otherwise the wrong data returns. below is the test result. I used 3 countries’ calendar. US, UK, and Japan. And in each calendar, I created all day events in three types of date format. A) yyyy-mm-dd B) yyyy-mm-ddZ C) yyyy-mm-dd+(-)hh:mm only type B format always returns the correct data.

1) US calendar (all type is OK) A: input start => 2006-09-18, end => 2006-09-19

   output  start => 2006-09-18, end => 2006-09-19

B: input start => 2006-09-18Z,end => 2006-09-19Z

   output  start => 2006-09-18, end => 2006-09-19

C: input start => 2006-09-18-08:00,end => 2006-09-19-08:00

   output  start => 2006-09-18,      end => 2006-09-19

2) UK calenar (A returns wrong data. B and C is OK) A: input start => 2006-09-18, end => 2006-09-19

   output  start => 2006-09-17, end => 2006-09-18

B: input start => 2006-09-18Z,end => 2006-09-19Z

   output  start => 2006-09-18, end => 2006-09-19

C: input start => 2006-09-18-00:00,end => 2006-09-19-00:00

   output  start => 2006-09-18,      end => 2006-09-19

3) Japan calendar (A and C returns wrong data. only B is OK) A: input start => 2006-09-18, end => 2006-09-19

   output  start => 2006-09-17, end => 2006-09-18

B: input start => 2006-09-18Z,end => 2006-09-19Z

   output  start => 2006-09-18, end => 2006-09-19

C: input start => 2006-09-18+09:00,end => 2006-09-19+09:00

   output  start => 2006-09-17,      end => 2006-09-18

convert String to Time

[Source]

     # File lib/googlecalendar/event.rb, line 261
261:     def str_to_time(st)
262:       ret = nil
263:       if st.is_a? Time then
264:         ret = st
265:       elsif st.is_a? String then 
266:         begin
267:           self.allday = false
268:           ret = Time.iso8601(st) 
269:         rescue 
270:           self.allday = true if st =~ /\d{4}-\d{2}-\d{2}/ # yyyy-mm-dd
271:           ret = Time.parse(st)
272:         end
273:       end
274:       ret
275:     end

returns string represents date or datetime

[Source]

     # File lib/googlecalendar/event.rb, line 278
278:     def time_to_str(dt)
279:       ret = nil
280:       if dt.nil?
281:         ret = ""
282:       else
283:         ret = dt.iso8601
284:         ret[10..-1] = "Z" if self.allday # yyyy-mm-ddZ
285:       end
286:       ret
287:     end

set xml data to attributes of an instance

[Source]

     # File lib/googlecalendar/event.rb, line 189
189:     def xml_to_instance
190:       ATTRIBUTES_MAP.each do |name, hash| 
191:         elem = @xml.root.elements[hash["element"]]
192:         unless elem.nil?
193:           val = (hash.has_key?("attribute") ? elem.attributes[hash["attribute"]] : elem.text)
194:           val = self.send(hash["from_xml"], val) if hash.has_key?("from_xml")
195:           self.send(name+"=", val)
196:         end
197:       end
198:       self.status = :old
199: 
200:       @xml.root.elements.each("link") do |link|
201:         @feed = link.attributes["href"] if link.attributes["rel"] == "edit"
202:       end
203:     end

[Validate]