Class: Vpim::Icalendar
- Inherits:
-
Object
- Object
- Vpim::Icalendar
- Includes:
- Vpim
- Defined in:
- lib/vpim/icalendar.rb,
lib/vpim/vtodo.rb,
lib/vpim/vevent.rb,
lib/vpim/address.rb,
lib/vpim/vjournal.rb,
lib/vpim/property/base.rb,
lib/vpim/property/common.rb,
lib/vpim/property/location.rb,
lib/vpim/property/priority.rb,
lib/vpim/property/resources.rb,
lib/vpim/property/recurrence.rb
Overview
An iCalendar.
A Calendar is some meta-information followed by a sequence of components.
Defined components are Event, Todo, Freebusy, Journal, and Timezone, each of which are represented by their own class, though they share many properties in common. For example, Event and Todo may both contain multiple Alarm components.
Reference
The iCalendar format is specified by a series of IETF documents:
-
rfc2445.txt: Internet Calendaring and Scheduling Core Object Specification
-
rfc2446.txt: iCalendar Transport-Independent Interoperability Protocol (iTIP) Scheduling Events, BusyTime, To-dos and Journal Entries
-
rfc2447.txt: iCalendar Message-Based Interoperability Protocol
iCalendar and vCalendar
iCalendar files have VERSION:2.0 and vCalendar have VERSION:1.0. iCalendar (RFC 2445) is based on vCalendar, but but is not very compatible. While much appears to be similar, the recurrence rule syntax is completely different.
iCalendars are usually transmitted in files with .ics
extensions.
Defined Under Namespace
Modules: Bnf, Property, Set Classes: Address, Vevent, Vjournal, Vtodo
Constant Summary
Constants included from Vpim
Class Method Summary collapse
-
.create(fields = []) ⇒ Object
Create a new Icalendar object with the minimal set of fields for a valid Calendar.
-
.create2(args = nil) ⇒ Object
FIXME - could take mandatory fields as an arguments FIXME - args: support PRODID FIXME - yield an Icalendar::Maker if block provided FIXME - maker#prodid=.
-
.create_reply(fields = []) ⇒ Object
Create a new Icalendar object with a protocol method of REPLY.
-
.decode(cal, e = nil) ⇒ Object
Decode iCalendar data into an array of Icalendar objects.
-
.decode_duration(str) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#add_event(&block) ⇒ Object
Add and event to this calendar.
-
#calscale ⇒ Object
The value of the CALSCALE: property, or “GREGORIAN” if CALSCALE: is not present.
-
#components(klass = Object) ⇒ Object
The array of all supported calendar components.
-
#encode(width = nil) ⇒ Object
(also: #to_s)
Encode the Calendar as a string.
-
#events ⇒ Object
For backwards compatibility.
-
#fields ⇒ Object
Used during encoding.
-
#initialize(fields) ⇒ Icalendar
constructor
Create a new Icalendar object from
fields
, an array of DirectoryInfo::Field objects. -
#producer ⇒ Object
The value of the PRODID field, an unstructured string meant to identify the software which encoded the Calendar data.
-
#protocol ⇒ Object
The value of the METHOD field.
-
#protocol?(method) ⇒ Boolean
Check if the protocol method is
method
. -
#push(component) ⇒ Object
Push a calendar component onto the calendar.
-
#todos ⇒ Object
For backwards compatibility.
-
#version ⇒ Object
The iCalendar version multiplied by 10 as an Integer.
Methods included from Vpim
array_datetime_to_time, decode_date, decode_date_list, decode_date_time, decode_date_time_list, decode_date_time_to_datetime, decode_date_to_date, decode_integer, decode_list, decode_text, decode_text_list, decode_time, decode_time_list, decode_time_to_time, encode_date, encode_date_time, encode_paramtext, encode_paramvalue, encode_text, encode_text_list, encode_time, expand, outer_inner, unfold, version
Constructor Details
#initialize(fields) ⇒ Icalendar
Create a new Icalendar object from fields
, an array of DirectoryInfo::Field objects.
When decoding Calendar data, you would usually use Icalendar.decode(), which decodes the data into the field arrays, and calls this method for each Calendar it finds.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/vpim/icalendar.rb', line 62 def initialize(fields) #:nodoc: # seperate into the outer-level fields, and the arrays of component # fields outer, inner = Vpim.outer_inner(fields) # Make a dirinfo out of outer, and check its an iCalendar @properties = DirectoryInfo.create(outer) @properties.check_begin_end('VCALENDAR') @components = [] factory = { 'VEVENT' => Vevent, 'VTODO' => Vtodo, 'VJOURNAL' => Vjournal, } inner.each do |component| name = component.first unless name.name? 'BEGIN' raise InvalidEncodingError, "calendar component begins with #{name.name}, instead of BEGIN!" end name = name.value if klass = factory[name] @components << klass.new(component) end end end |
Class Method Details
.create(fields = []) ⇒ Object
Create a new Icalendar object with the minimal set of fields for a valid Calendar. If specified, fields
must be an array of DirectoryInfo::Field objects to add. They can override the the default Calendar fields, so, for example, this can be used to set a custom PRODID field.
118 119 120 121 122 123 124 125 126 127 |
# File 'lib/vpim/icalendar.rb', line 118 def Icalendar.create(fields=[]) di = DirectoryInfo.create( [ DirectoryInfo::Field.create('VERSION', '2.0') ], 'VCALENDAR' ) DirectoryInfo::Field.create_array(fields).each { |f| di.push_unique f } di.push_unique DirectoryInfo::Field.create('PRODID', Vpim::PRODID) di.push_unique DirectoryInfo::Field.create('CALSCALE', "Gregorian") new(di.to_a) end |
.create2(args = nil) ⇒ Object
FIXME - could take mandatory fields as an arguments FIXME - args: support PRODID FIXME - yield an Icalendar::Maker if block provided FIXME - maker#prodid=
104 105 106 107 108 109 110 111 112 |
# File 'lib/vpim/icalendar.rb', line 104 def Icalendar.create2(args = nil) # FIXME - make the primary API di = DirectoryInfo.create( [ DirectoryInfo::Field.create('VERSION', '2.0') ], 'VCALENDAR' ) di.push_unique DirectoryInfo::Field.create('PRODID', Vpim::PRODID) di.push_unique DirectoryInfo::Field.create('CALSCALE', "Gregorian") new(di.to_a) end |
.create_reply(fields = []) ⇒ Object
Create a new Icalendar object with a protocol method of REPLY.
Meeting requests, and such, are Calendar containers with a protocol method of REQUEST, and contains some number of Events, Todos, etc., that may need replying to. In order to reply to any of these components of a request, you must first build a Calendar object to hold your reply components.
This method builds the reply Calendar, you then will add to it replies to the specific components of the request Calendar that you are replying to. If you have any particular fields that you want to be in the Calendar, other than the defaults, then can be supplied as fields
, an array of Field objects.
142 143 144 145 146 |
# File 'lib/vpim/icalendar.rb', line 142 def Icalendar.create_reply(fields=[]) fields << DirectoryInfo::Field.create('METHOD', 'REPLY') Icalendar.create(fields) end |
.decode(cal, e = nil) ⇒ Object
Decode iCalendar data into an array of Icalendar objects.
Since iCalendars are self-delimited (by a BEGIN:VCALENDAR and an END:VCALENDAR), multiple iCalendars can be concatenated into a single file.
cal must be String or IO, or implement #each by returning each line in the input as those classes do.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/vpim/icalendar.rb', line 231 def Icalendar.decode(cal, e = nil) entities = Vpim.(Vpim.decode(cal)) # Since all iCalendars must have a begin/end, the top-level should # consist entirely of entities/arrays, even if its a single iCalendar. if entities.detect { |e| ! e.kind_of? Array } raise "Not a valid iCalendar" end calendars = [] entities.each do |e| calendars << new(e) end calendars end |
.decode_duration(str) ⇒ Object
:nodoc:
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/vpim/icalendar.rb', line 183 def Icalendar.decode_duration(str) #:nodoc: unless match = %r{\s*#{Bnf::DURATION}\s*}.match(str) raise InvalidEncodingError, "duration not valid (#{str})" end dur = 0 # Remember: match[0] is the whole match string, match[1] is $1, etc. # Week if match[2] dur = match[2].to_i end # Days dur *= 7 if match[3] dur += match[3].to_i end # Hours dur *= 24 if match[4] dur += match[4].to_i end # Minutes dur *= 60 if match[5] dur += match[5].to_i end # Seconds dur *= 60 if match[6] dur += match[6].to_i end if match[1] && match[1] == '-' dur = -dur end dur end |
Instance Method Details
#add_event(&block) ⇒ Object
Add and event to this calendar.
Yields an event maker, Icalendar::Vevent::Maker.
96 97 98 |
# File 'lib/vpim/icalendar.rb', line 96 def add_event(&block) #:yield:event push Vevent::Maker.make( &block ) end |
#calscale ⇒ Object
The value of the CALSCALE: property, or “GREGORIAN” if CALSCALE: is not present.
This is of academic interest, really because there aren’t any other calendar scales defined, and given that its hard enough just dealing with Gregorian calendars, there probably won’t be.
290 291 292 |
# File 'lib/vpim/icalendar.rb', line 290 def calscale proptext('CALSCALE') || 'GREGORIAN' end |
#components(klass = Object) ⇒ Object
The array of all supported calendar components. If a class is provided, return only the components of that class.
If a block is provided, yield the components instead of returning them.
Examples:
calendar.components(Vpim::Icalendar::Vevent)
=> array of all calendar components
calendar.components(Vpim::Icalendar::Vtodo) {|c| c... }
=> yield all todo components
calendar.components {|c| c... }
=> yield all components
308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'lib/vpim/icalendar.rb', line 308 def components(klass=Object) #:yields:component # TODO - should this take an interval: t0,t1? unless block_given? return @components.select{|c| klass === c}.freeze end @components.each do |c| if klass === c yield c end end self end |
#encode(width = nil) ⇒ Object Also known as: to_s
Encode the Calendar as a string. The width is the maximum width of the encoded lines, it can be specified, but is better left to the default.
158 159 160 161 162 163 |
# File 'lib/vpim/icalendar.rb', line 158 def encode(width=nil) # We concatenate the fields of all objects, create a DirInfo, then # encode it. di = DirectoryInfo.create(self.fields.flatten) di.encode(width) end |
#events ⇒ Object
For backwards compatibility. Use #components.
324 325 326 |
# File 'lib/vpim/icalendar.rb', line 324 def events #:nodoc: components Icalendar::Vevent end |
#fields ⇒ Object
Used during encoding.
149 150 151 152 153 154 |
# File 'lib/vpim/icalendar.rb', line 149 def fields # :nodoc: f = @properties.to_a last = f.pop @components.each { |c| f << c.fields } f.push last end |
#producer ⇒ Object
The value of the PRODID field, an unstructured string meant to identify the software which encoded the Calendar data.
265 266 267 268 269 |
# File 'lib/vpim/icalendar.rb', line 265 def producer #f = @properties.field('PRODID') #f && f.to_text @properties.text('PRODID').first end |
#protocol ⇒ Object
The value of the METHOD field. Protocol methods are used when iCalendars are exchanged in a calendar messaging system, such as iTIP or iMIP. When METHOD is not specified, the Calendar object is merely being used to transport a snapshot of some calendar information; without the intention of conveying a scheduling semantic.
Note that this method can’t be called method
, thats already a method of Object.
279 280 281 282 |
# File 'lib/vpim/icalendar.rb', line 279 def protocol m = @properties['METHOD'] m ? m.upcase : m end |
#protocol?(method) ⇒ Boolean
Check if the protocol method is method
179 180 181 |
# File 'lib/vpim/icalendar.rb', line 179 def protocol?(method) Vpim::Methods.casecmp?(protocol, method) end |
#push(component) ⇒ Object
Push a calendar component onto the calendar.
168 169 170 171 172 173 174 175 176 |
# File 'lib/vpim/icalendar.rb', line 168 def push(component) case component when Vevent, Vtodo, Vjournal @components << component else raise ArgumentError, "can't add a #{component.type} to a calendar" end self end |
#todos ⇒ Object
For backwards compatibility. Use #components.
329 330 331 |
# File 'lib/vpim/icalendar.rb', line 329 def todos #:nodoc: components Icalendar::Vtodo end |
#version ⇒ Object
The iCalendar version multiplied by 10 as an Integer. If no VERSION field is present (which is non-conformant), nil is returned. iCalendar must have a version of 20, and vCalendar would have a version of 10.
252 253 254 255 256 257 258 259 260 261 |
# File 'lib/vpim/icalendar.rb', line 252 def version v = @properties['VERSION'] unless v raise InvalidEncodingError, "Invalid calendar, no version field!" end v = v.to_f * 10 v = v.to_i end |