ri_cal 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. data/History.txt +45 -0
  2. data/Manifest.txt +129 -0
  3. data/README.txt +394 -0
  4. data/Rakefile +31 -0
  5. data/bin/ri_cal +8 -0
  6. data/component_attributes/alarm.yml +10 -0
  7. data/component_attributes/calendar.yml +4 -0
  8. data/component_attributes/component_property_defs.yml +180 -0
  9. data/component_attributes/event.yml +45 -0
  10. data/component_attributes/freebusy.yml +16 -0
  11. data/component_attributes/journal.yml +35 -0
  12. data/component_attributes/timezone.yml +3 -0
  13. data/component_attributes/timezone_period.yml +11 -0
  14. data/component_attributes/todo.yml +46 -0
  15. data/copyrights.txt +1 -0
  16. data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
  17. data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
  18. data/docs/incrementers.txt +7 -0
  19. data/docs/rfc2445.pdf +0 -0
  20. data/lib/ri_cal.rb +144 -0
  21. data/lib/ri_cal/component.rb +247 -0
  22. data/lib/ri_cal/component/alarm.rb +21 -0
  23. data/lib/ri_cal/component/calendar.rb +219 -0
  24. data/lib/ri_cal/component/event.rb +60 -0
  25. data/lib/ri_cal/component/freebusy.rb +18 -0
  26. data/lib/ri_cal/component/journal.rb +30 -0
  27. data/lib/ri_cal/component/t_z_info_timezone.rb +123 -0
  28. data/lib/ri_cal/component/timezone.rb +196 -0
  29. data/lib/ri_cal/component/timezone/daylight_period.rb +25 -0
  30. data/lib/ri_cal/component/timezone/standard_period.rb +23 -0
  31. data/lib/ri_cal/component/timezone/timezone_period.rb +53 -0
  32. data/lib/ri_cal/component/todo.rb +43 -0
  33. data/lib/ri_cal/core_extensions.rb +6 -0
  34. data/lib/ri_cal/core_extensions/array.rb +7 -0
  35. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  36. data/lib/ri_cal/core_extensions/date.rb +13 -0
  37. data/lib/ri_cal/core_extensions/date/conversions.rb +61 -0
  38. data/lib/ri_cal/core_extensions/date_time.rb +15 -0
  39. data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
  40. data/lib/ri_cal/core_extensions/object.rb +8 -0
  41. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  42. data/lib/ri_cal/core_extensions/string.rb +8 -0
  43. data/lib/ri_cal/core_extensions/string/conversions.rb +63 -0
  44. data/lib/ri_cal/core_extensions/time.rb +13 -0
  45. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  46. data/lib/ri_cal/core_extensions/time/conversions.rb +61 -0
  47. data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
  48. data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +88 -0
  49. data/lib/ri_cal/floating_timezone.rb +32 -0
  50. data/lib/ri_cal/invalid_property_value.rb +8 -0
  51. data/lib/ri_cal/invalid_timezone_identifer.rb +20 -0
  52. data/lib/ri_cal/occurrence_enumerator.rb +206 -0
  53. data/lib/ri_cal/occurrence_period.rb +17 -0
  54. data/lib/ri_cal/parser.rb +138 -0
  55. data/lib/ri_cal/properties/alarm.rb +390 -0
  56. data/lib/ri_cal/properties/calendar.rb +164 -0
  57. data/lib/ri_cal/properties/event.rb +1526 -0
  58. data/lib/ri_cal/properties/freebusy.rb +594 -0
  59. data/lib/ri_cal/properties/journal.rb +1240 -0
  60. data/lib/ri_cal/properties/timezone.rb +151 -0
  61. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  62. data/lib/ri_cal/properties/todo.rb +1562 -0
  63. data/lib/ri_cal/property_value.rb +149 -0
  64. data/lib/ri_cal/property_value/array.rb +27 -0
  65. data/lib/ri_cal/property_value/cal_address.rb +11 -0
  66. data/lib/ri_cal/property_value/date.rb +175 -0
  67. data/lib/ri_cal/property_value/date_time.rb +335 -0
  68. data/lib/ri_cal/property_value/date_time/additive_methods.rb +44 -0
  69. data/lib/ri_cal/property_value/date_time/time_machine.rb +181 -0
  70. data/lib/ri_cal/property_value/date_time/timezone_support.rb +96 -0
  71. data/lib/ri_cal/property_value/duration.rb +110 -0
  72. data/lib/ri_cal/property_value/geo.rb +11 -0
  73. data/lib/ri_cal/property_value/integer.rb +12 -0
  74. data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
  75. data/lib/ri_cal/property_value/period.rb +82 -0
  76. data/lib/ri_cal/property_value/recurrence_rule.rb +145 -0
  77. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +97 -0
  78. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +79 -0
  79. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +148 -0
  80. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +53 -0
  81. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +31 -0
  82. data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +793 -0
  83. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
  84. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +60 -0
  85. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
  86. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +49 -0
  87. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
  88. data/lib/ri_cal/property_value/text.rb +40 -0
  89. data/lib/ri_cal/property_value/uri.rb +11 -0
  90. data/lib/ri_cal/property_value/utc_offset.rb +33 -0
  91. data/lib/ri_cal/required_timezones.rb +55 -0
  92. data/ri_cal.gemspec +49 -0
  93. data/sample_ical_files/from_ical_dot_app/test1.ics +38 -0
  94. data/script/console +10 -0
  95. data/script/destroy +14 -0
  96. data/script/generate +14 -0
  97. data/script/txt2html +71 -0
  98. data/spec/ri_cal/component/alarm_spec.rb +12 -0
  99. data/spec/ri_cal/component/calendar_spec.rb +54 -0
  100. data/spec/ri_cal/component/event_spec.rb +601 -0
  101. data/spec/ri_cal/component/freebusy_spec.rb +12 -0
  102. data/spec/ri_cal/component/journal_spec.rb +37 -0
  103. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +36 -0
  104. data/spec/ri_cal/component/timezone_spec.rb +218 -0
  105. data/spec/ri_cal/component/todo_spec.rb +112 -0
  106. data/spec/ri_cal/component_spec.rb +224 -0
  107. data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
  108. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
  109. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
  110. data/spec/ri_cal/occurrence_enumerator_spec.rb +573 -0
  111. data/spec/ri_cal/parser_spec.rb +303 -0
  112. data/spec/ri_cal/property_value/date_spec.rb +53 -0
  113. data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
  114. data/spec/ri_cal/property_value/duration_spec.rb +126 -0
  115. data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
  116. data/spec/ri_cal/property_value/period_spec.rb +49 -0
  117. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
  118. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
  119. data/spec/ri_cal/property_value/text_spec.rb +25 -0
  120. data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
  121. data/spec/ri_cal/property_value_spec.rb +125 -0
  122. data/spec/ri_cal/required_timezones_spec.rb +67 -0
  123. data/spec/ri_cal_spec.rb +53 -0
  124. data/spec/spec.opts +4 -0
  125. data/spec/spec_helper.rb +46 -0
  126. data/tasks/gem_loader/load_active_support.rb +3 -0
  127. data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
  128. data/tasks/ri_cal.rake +410 -0
  129. data/tasks/spec.rake +50 -0
  130. metadata +221 -0
@@ -0,0 +1,45 @@
1
+ === 0.0.9
2
+ * Fixed http://rick_denatale.lighthouseapp.com/projects/30941/tickets/4
3
+ Missing comparison methods in PropertyValue::Date
4
+ * Fixed http://rick_denatale.lighthouseapp.com/projects/30941/tickets/6
5
+ Type of dtstart and dtend (DATE or DATETIME) now preserved on enumeration
6
+ === 0.0.8
7
+ * Fixed http://rick_denatale.lighthouseapp.com/projects/30941-ri_cal/tickets/1
8
+ EXDATE and RDATE now pick up the timezone from DateTime, Time, and TimeWithZone values
9
+ * Fixed http://rick_denatale.lighthouseapp.com/projects/30941/tickets/2
10
+ Missing arithmetic methods in PropertyValue::Date
11
+ * Fixed http://rick_denatale.lighthouseapp.com/projects/30941/tickets/3
12
+ Components with no recurrence rules or rdate properties failed on enumeration, they now
13
+ will enumerate a single occurrence
14
+
15
+ === 0.0.7
16
+ * Fixed a bug relating to properly recognizing ActiveRecord::TimeWithZone
17
+ * DATETIME propertyvalues will now return an instance of TimeWithZone instead of DateTime when
18
+ activesupport is present, and it is appropriate. See the README for details
19
+ === 0.0.6
20
+ * Added rake tasks to run specs with either the tzinfo gem or activesupport (<=2.2)
21
+ * Default rake task now runs both of these
22
+ === 0.0.5
23
+ * Fixed a bug in occurrence enumeration reported by paulsm on github
24
+ === 0.0.4
25
+ * Fixed a bug in imported timezones reported by paulsm on github
26
+ === 0.0.3
27
+ * Added tzid method to Ruby Time and DateTime instances, and to ActiveRecord::TimeWithZone if it is defined this method is used to determine the desired
28
+ timezone when an instance of one of these classes is given as the value of a datetime property. If the tzid is nil then the default tzid is used,
29
+ if it is set to :floating then the property will be a floating time.
30
+ * Removed the ability to pass an array with a tzid string and a date-time since the above made it unnecessary
31
+ * The ruby datetime property returned from the ruby_value method on the DateTime property will return an instance of ::DateTime with:
32
+ ** The proper utc offset
33
+ ** The tzid set to the right tzid
34
+ * Made exdate/rdate building possible
35
+ * Added a default_tzid attribute to the Calendar component, if this attribute is not set for a particular calendar it will delegate to the default set
36
+ for the DateTime property class.
37
+ * Added fix patches from
38
+ ** http://github.com/kjwierenga/ri_cal
39
+ ** http://github.com/wesmaldonado/ri_cal
40
+
41
+ === 0.0.2
42
+ * Fixed gemspec
43
+ == 0.0.1
44
+
45
+ * Initial public release
@@ -0,0 +1,129 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/ri_cal
6
+ component_attributes/alarm.yml
7
+ component_attributes/calendar.yml
8
+ component_attributes/component_property_defs.yml
9
+ component_attributes/event.yml
10
+ component_attributes/freebusy.yml
11
+ component_attributes/journal.yml
12
+ component_attributes/timezone.yml
13
+ component_attributes/timezone_period.yml
14
+ component_attributes/todo.yml
15
+ copyrights.txt
16
+ docs/draft-ietf-calsify-2446bis-08.txt
17
+ docs/draft-ietf-calsify-rfc2445bis-09.txt
18
+ docs/incrementers.txt
19
+ docs/rfc2445.pdf
20
+ lib/ri_cal.rb
21
+ lib/ri_cal/component.rb
22
+ lib/ri_cal/component/alarm.rb
23
+ lib/ri_cal/component/calendar.rb
24
+ lib/ri_cal/component/event.rb
25
+ lib/ri_cal/component/freebusy.rb
26
+ lib/ri_cal/component/journal.rb
27
+ lib/ri_cal/component/t_z_info_timezone.rb
28
+ lib/ri_cal/component/timezone.rb
29
+ lib/ri_cal/component/timezone/daylight_period.rb
30
+ lib/ri_cal/component/timezone/standard_period.rb
31
+ lib/ri_cal/component/timezone/timezone_period.rb
32
+ lib/ri_cal/component/todo.rb
33
+ lib/ri_cal/core_extensions.rb
34
+ lib/ri_cal/core_extensions/array.rb
35
+ lib/ri_cal/core_extensions/array/conversions.rb
36
+ lib/ri_cal/core_extensions/date.rb
37
+ lib/ri_cal/core_extensions/date/conversions.rb
38
+ lib/ri_cal/core_extensions/date_time.rb
39
+ lib/ri_cal/core_extensions/date_time/conversions.rb
40
+ lib/ri_cal/core_extensions/object.rb
41
+ lib/ri_cal/core_extensions/object/conversions.rb
42
+ lib/ri_cal/core_extensions/string.rb
43
+ lib/ri_cal/core_extensions/string/conversions.rb
44
+ lib/ri_cal/core_extensions/time.rb
45
+ lib/ri_cal/core_extensions/time/calculations.rb
46
+ lib/ri_cal/core_extensions/time/conversions.rb
47
+ lib/ri_cal/core_extensions/time/tzid_access.rb
48
+ lib/ri_cal/core_extensions/time/week_day_predicates.rb
49
+ lib/ri_cal/floating_timezone.rb
50
+ lib/ri_cal/invalid_property_value.rb
51
+ lib/ri_cal/invalid_timezone_identifer.rb
52
+ lib/ri_cal/occurrence_enumerator.rb
53
+ lib/ri_cal/occurrence_period.rb
54
+ lib/ri_cal/parser.rb
55
+ lib/ri_cal/properties/alarm.rb
56
+ lib/ri_cal/properties/calendar.rb
57
+ lib/ri_cal/properties/event.rb
58
+ lib/ri_cal/properties/freebusy.rb
59
+ lib/ri_cal/properties/journal.rb
60
+ lib/ri_cal/properties/timezone.rb
61
+ lib/ri_cal/properties/timezone_period.rb
62
+ lib/ri_cal/properties/todo.rb
63
+ lib/ri_cal/property_value.rb
64
+ lib/ri_cal/property_value/array.rb
65
+ lib/ri_cal/property_value/cal_address.rb
66
+ lib/ri_cal/property_value/date.rb
67
+ lib/ri_cal/property_value/date_time.rb
68
+ lib/ri_cal/property_value/date_time/additive_methods.rb
69
+ lib/ri_cal/property_value/date_time/time_machine.rb
70
+ lib/ri_cal/property_value/date_time/timezone_support.rb
71
+ lib/ri_cal/property_value/duration.rb
72
+ lib/ri_cal/property_value/geo.rb
73
+ lib/ri_cal/property_value/integer.rb
74
+ lib/ri_cal/property_value/occurrence_list.rb
75
+ lib/ri_cal/property_value/period.rb
76
+ lib/ri_cal/property_value/recurrence_rule.rb
77
+ lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb
78
+ lib/ri_cal/property_value/recurrence_rule/enumerator.rb
79
+ lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb
80
+ lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb
81
+ lib/ri_cal/property_value/recurrence_rule/numbered_span.rb
82
+ lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb
83
+ lib/ri_cal/property_value/recurrence_rule/recurring_day.rb
84
+ lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb
85
+ lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb
86
+ lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb
87
+ lib/ri_cal/property_value/recurrence_rule/validations.rb
88
+ lib/ri_cal/property_value/text.rb
89
+ lib/ri_cal/property_value/uri.rb
90
+ lib/ri_cal/property_value/utc_offset.rb
91
+ lib/ri_cal/required_timezones.rb
92
+ ri_cal.gemspec
93
+ sample_ical_files/from_ical_dot_app/test1.ics
94
+ script/console
95
+ script/destroy
96
+ script/generate
97
+ script/txt2html
98
+ spec/ri_cal/component/alarm_spec.rb
99
+ spec/ri_cal/component/calendar_spec.rb
100
+ spec/ri_cal/component/event_spec.rb
101
+ spec/ri_cal/component/freebusy_spec.rb
102
+ spec/ri_cal/component/journal_spec.rb
103
+ spec/ri_cal/component/t_z_info_timezone_spec.rb
104
+ spec/ri_cal/component/timezone_spec.rb
105
+ spec/ri_cal/component/todo_spec.rb
106
+ spec/ri_cal/component_spec.rb
107
+ spec/ri_cal/core_extensions/string/conversions_spec.rb
108
+ spec/ri_cal/core_extensions/time/calculations_spec.rb
109
+ spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb
110
+ spec/ri_cal/occurrence_enumerator_spec.rb
111
+ spec/ri_cal/parser_spec.rb
112
+ spec/ri_cal/property_value/date_spec.rb
113
+ spec/ri_cal/property_value/date_time_spec.rb
114
+ spec/ri_cal/property_value/duration_spec.rb
115
+ spec/ri_cal/property_value/occurrence_list_spec.rb
116
+ spec/ri_cal/property_value/period_spec.rb
117
+ spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb
118
+ spec/ri_cal/property_value/recurrence_rule_spec.rb
119
+ spec/ri_cal/property_value/text_spec.rb
120
+ spec/ri_cal/property_value/utc_offset_spec.rb
121
+ spec/ri_cal/property_value_spec.rb
122
+ spec/ri_cal/required_timezones_spec.rb
123
+ spec/ri_cal_spec.rb
124
+ spec/spec.opts
125
+ spec/spec_helper.rb
126
+ tasks/gem_loader/load_active_support.rb
127
+ tasks/gem_loader/load_tzinfo_gem.rb
128
+ tasks/ri_cal.rake
129
+ tasks/spec.rake
@@ -0,0 +1,394 @@
1
+ == RI_CAL -- a new implementation of RFC2445 in Ruby
2
+ http://ri-cal.rubyforge.org/
3
+
4
+ by Rick DeNatale
5
+ == DESCRIPTION:
6
+
7
+ This is an UNOFFICIAL version. The public official version will be released on RubyForge. Github will be used
8
+ for interim versions. USE THIS VERSION AT YOUR OWN RISK.
9
+
10
+ A new Ruby implementation of RFC2445 iCalendar.
11
+
12
+ The existing Ruby iCalendar libraries (e.g. icalendar, vpim) provide for parsing and generating icalendar files,
13
+ but do not support important things like enumerating occurrences of repeating events.
14
+
15
+ This is a clean-slate implementation of RFC2445.
16
+
17
+ A Google group for discussion of this library has been set up http://groups.google.com/group/rical_gem
18
+
19
+ == FEATURES/PROBLEMS:
20
+
21
+ * All examples of recurring events in RFC 2445 are handled. RSpec examples are provided for them.
22
+
23
+ == SYNOPSIS:
24
+
25
+ === Components and properties
26
+
27
+ An iCalendar calendar comprises subcomponents like Events, Timezones and Todos. Each component may
28
+ have properties, for example an event has a dtstart property which defines the time (and date) on
29
+ which the event starts.
30
+
31
+ RiCal components will provide reasonable ruby objects as the values of these properties, and allow
32
+ the properties to be set to ruby objects which are reasonable for the particular property. For
33
+ example time properties like dtstart can be set to a ruby Time, DateTime or Date object, and will
34
+ return a DateTime or Date object when queried.
35
+
36
+ The methods for accessing the properties of each type of component are defined in a module with the
37
+ same name as the component class in the RiCal::properties module. For example the property
38
+ accessing methods for RiCal::Component::Event are defined in RiCal::Properties::Event
39
+
40
+ === Creating Calendars and Calendar Components
41
+
42
+ RiCal provides a builder DSL for creating calendars and calendar components. An example
43
+
44
+ RiCal.Calendar do
45
+ event do
46
+ description "MA-6 First US Manned Spaceflight"
47
+ dtstart DateTime.parse("2/20/1962 14:47:39")
48
+ dtend DateTime.parse("2/20/1962 19:43:02")
49
+ location "Cape Canaveral"
50
+ add_attendee "john.glenn@nasa.gov"
51
+ alarm do
52
+ description "Segment 51"
53
+ end
54
+ end
55
+ end
56
+
57
+ This style is for compatibility with the iCalendar and vpim to ease migration. The downside is that
58
+ the block is evaluated in the context of a different object which can cause surprises if the block
59
+ contains direct instance variable references or implicit references to self. Note that, in this
60
+ style, one must use 'declarative' method calls like dtstart to set values rather than more natural
61
+ attribute writer methods, like dtstart=
62
+
63
+ Alternatively you can pass a block with a single argument, in this case the component being built
64
+ will be passed as that argument
65
+
66
+ RiCal.Calendar do |cal|
67
+ cal.event do |event|
68
+ event.description = "MA-6 First US Manned Spaceflight"
69
+ event.dtstart = DateTime.parse("2/20/1962 14:47:39")
70
+ event.dtend = DateTime.parse("2/20/1962 19:43:02")
71
+ event.location = "Cape Canaveral"
72
+ event.add_attendee "john.glenn@nasa.gov"
73
+ event.alarm do
74
+ description "Segment 51"
75
+ end
76
+ end
77
+ end
78
+
79
+ As the example shows, the two styles can be mixed, the inner block which builds the alarm uses the
80
+ first style.
81
+
82
+ The blocks are evaluated in the context of an object which builds the calendar or calendar
83
+ component. method names starting with add_ or remove_ are sent to the component, method names which
84
+ correspond to a property value setter of the object being built will cause that setter to be sent
85
+ to the component with the provided value.
86
+
87
+ A method corresponding to the name of one of the components sub component will create the sub
88
+ component and evaluate a block if given in the context of the new subcomponent.
89
+
90
+ ==== Multiply occurring properties
91
+
92
+ Certain RFC Components have properties which may be specified multiple times, for example, an Event
93
+ may have zero or more comment properties, A component will have a family of methods for
94
+ building/manipulating such a property, e.g.
95
+
96
+ Event#comment:: will return an array of comment strings.
97
+ Event#comment=:: takes a single comment string and gives the event a single comment property,
98
+ replacing any existing comment property collection.
99
+ Event#comments=:: takes multiple comment string arguments and gives the event a comment property for each,
100
+ replacing any existing comment property collection.
101
+ Event#add_comment:: takes a single comment string argument and adds a comment property.
102
+ Event#add_comments:: takes multiple comment string arguments and adds a comment property for each.
103
+ Event#remove_comment:: takes a single comment string argument and removes an existing comment property with that value.
104
+ Event#remove_comments:: takes multiple comment string argument and removes an existing comment property with that value.
105
+
106
+
107
+ ==== Times, Time zones, and Floating Times
108
+
109
+ RFC2445 describes three different kinds of DATE-TIME values with respect to time zones:
110
+
111
+ 1. date-times with a local time. These have no actual time zone, instead they are to be
112
+ interpreted in the local time zone of the viewer. These floating times are used for things
113
+ like the New Years celebration which is observed at local midnight whether you happen to be
114
+ in Paris, London, or New York.
115
+
116
+ 2. date-times with UTC time. An application would either display these with an indication of
117
+ the time zone, or convert them to the viewer's time zone, perhaps depending on user settings.
118
+
119
+ 3. date-times with a specified time zone.
120
+
121
+ RiCal can be given ruby Time, DateTime, or Date objects for the value of properties requiring an
122
+ iCalendar DATE-TIME value. It can also be given a string
123
+
124
+ Note that a date only DATE-TIME value has no time zone by definition, effectively such values float
125
+ and describe a date as viewed by the user in his/her local time zone.
126
+
127
+ When a Ruby Time or DateTime instance is used to set properties with with a DATE-TIME value, it
128
+ needs to determine which of the three types it represents. RiCal is designed to make use of the
129
+ TimeWithZone support which has been part of the ActiveSupport component of Ruby on Rails since
130
+ Rails 2.2. However it's been carefully designed not to require Rails or ActiveSupport, but to
131
+ dynamically detect the presence of the TimeWithZone support.
132
+
133
+ RiCal adds accessor methods for a tzid attribute to the Ruby Time, and DateTime classes as well as
134
+ a set_tzid method which sets the tzid attribute and returns the receiver for convenience in
135
+ building calendars. If ActiveSupport::TimeWithZone is defined, a tzid instance method is defined
136
+ which returns the identifier of the time zone.
137
+
138
+ When the value of a DATE-TIME property is set to a value, the following processing occurs:
139
+
140
+ * If the value is a string, then it must be a valid rfc 2445 date or datetime string optionally
141
+ preceded by a parameter specification e.g
142
+
143
+ "20010911" will be interpreted as a date
144
+
145
+ "20090530T123000Z" will be interpreted as the time May 30, 2009 at 12:30:00 UTC
146
+
147
+ "20090530T123000" will be interpreted as the time May 30, 2009 with a floating time zone
148
+
149
+ "TZID=America/New_York:20090530T123000" will be interpreted as the time May 30, 2009 in the time zone identified by "America/New_York"
150
+
151
+ * If the value is a Date it will be interpreted as that date
152
+ * If the value is a Time, DateTime, or TimeWithZone then the tzid attribute will determine the
153
+ time zone. If tzid returns nil then the default tzid will be used.
154
+
155
+ ==== Default TZID
156
+
157
+ The PropertyValue::DateTime class has a default_tzid attribute which is initialized to "UTC".
158
+
159
+ The Component::Calendar class also has a default_tzid attribute, which may be set, but if it is not
160
+ set the default_tzid of the PropertyValue::DateTime class will be used.
161
+
162
+ To set the interpreting of Times and DateTimes which have no tzid as floating times, set the
163
+ default_tzid for Component::Calendar and/or PropertyValue::DateTime to :floating.
164
+
165
+ Also note that time zone identifiers are not standardized by RFC 2445. For an RiCal originated
166
+ calendar time zone identifiers recognized by the TZInfo gem, or the TZInfo implementation provided
167
+ by ActiveSupport as the case may be may be used. The valid time zone identifiers for a non-RiCal
168
+ generated calendar imported into RiCalendar are determined by the VTIMEZONE compoents within the
169
+ imported calendar.
170
+
171
+ If you use a timezone identifer within a calendar which is not defined within the calendar it will
172
+ detected at the time you try to convert a timezone. In this case an InvalidTimezoneIdentifier error
173
+ will be raised by the conversion method.
174
+
175
+ To explicitly set a floating time you can use the method #with_floating_timezone on Time or
176
+ DateTime instances as in
177
+
178
+ event.dtstart = Time.parse("1/1/2010 00:00:00").with_floating_timezone
179
+
180
+ or the equivalent
181
+
182
+ event.dtstart = Time.parse("1/1/2010 00:00:00").set_tzid(:floating)
183
+
184
+ === RiCal produced Calendars and Tzinfo
185
+
186
+ Calendars created by the RiCal Builder DSL use TZInfo as a source of time zone definition
187
+ information. RFC 2445 does not specify standard names for time zones, so each time zone identifier
188
+ (tzid) within an icalendar data stream must correspond to a VTIMEZONE component in that data
189
+ stream.
190
+
191
+ When an RiCal calendar is exported to an icalendar data stream, the needed VTIMEZONE components
192
+ will be generated. In addition a parameter is added to the PRODID property of the calendar which
193
+ identifies that the source of tzids is tzinfo. For purposes of this documentation such a calendar
194
+ is called a tzinfo calendar.
195
+
196
+ When RiCal imports an icalendar data stream produced by another library or application, such as
197
+ Apple's ical.app, or Google mail, it will be recognized as not being a non-tzinfo calendar, and any
198
+ tzids will be resolved using the included VTIMEZONEs. Note that these calendars may well use tzids
199
+ which are not recognizable by the tzinfo gem or by the similar code provided by ActiveSupport,
200
+ so care is needed in using them.
201
+
202
+ === Ruby values of DATETIME properties
203
+
204
+ The result of accessing the value of a DATETIME property (e.g. event.dtstart) depends on several
205
+ factors:
206
+
207
+ * If the property has a DATE value, then the result will be a Ruby Date object.
208
+
209
+ * Otherwise, if the property has a DATETIME value with a floating timezone, then the result will
210
+ be a Ruby DateTime object, the tzid attribute will be set to :floating, and will respond
211
+ truthily to has_floating_timezone?
212
+
213
+ * Otherwise if the value is attached to a property contained in a non-tzinfo calendar, or if the
214
+ ActiveSupport gem is not loaded, then the result will be a Ruby DateTime object, with the proper
215
+ offset from UTC, and with the tzid property set.
216
+
217
+ * Finally, if the value is attached to a property contained in a tzinfo calendar and the
218
+ ActiveSupport gem is loaded, then the result will be an ActiveSupport::TimeWithZone with the
219
+ proper tzid.
220
+
221
+ ==== RDATE, and EXDATE properties (Occurrence Lists)
222
+
223
+ A calendar component which supports recurrence properties (e.g. Event) may have zero or more RDATE
224
+ and or EXDATE properties. Each RDATE/EXDATE property in turn specifies one or more occurrences to
225
+ be either added to or removed from the component's recurrence list. Each element of the list may be
226
+ either a DATE, a DATETIME, or a PERIOD, or the RFC 2445 string representation of one of these:
227
+
228
+ event.rdate = "20090305"
229
+ event.rdate = "20090305T120000"
230
+ event.rdate = "20090305T120000/P1H30M"
231
+
232
+ It can also have multiple occurrences, specified as multiple parameters:
233
+
234
+ event.rdate = "20090305T120000", "20090405T120000"
235
+ event.rdate = DateTime.parse("12 December, 2005 3:00 pm"), DateTime.civil(2001, 3, 4, 15, 30, 0)
236
+
237
+
238
+ Multiple string values can be combined separated by commas:
239
+
240
+ event.rdate = "20090305T120000,20090405T120000"
241
+
242
+
243
+ An occurrence list has one set of parameters, so only one timezone can be used, the timezone may
244
+ be set explicitly via the first argument. If the first argument is a string, it is first split on
245
+ commas. Then if the first segment (up to the first comma if any) is not a valid RFC 2445
246
+ representation of a DATE, DATETIME, or PERIOD, then it will be used as the timezone for the
247
+ occurrence list. Otherwise the arguments must have the same time zone or an InvalidPropertyValue
248
+ error will be raised.
249
+ === Parsing
250
+
251
+ RiCal can parse icalendar data from either a string or a Ruby io object.
252
+
253
+ The data may consist of one or more icalendar calendars, or one or more icalendar components (e.g.
254
+ one or more VEVENT, or VTODO objects.)
255
+
256
+ In either case the result will be an array of components.
257
+ ==== From a string
258
+ RiCal.parse_string <<ENDCAL
259
+ BEGIN:VCALENDAR
260
+ X-WR-TIMEZONE:America/New_York
261
+ PRODID:-//Apple Inc.//iCal 3.0//EN
262
+ CALSCALE:GREGORIAN
263
+ X-WR-CALNAME:test
264
+ VERSION:2.0
265
+ X-WR-RELCALID:1884C7F8-BC8E-457F-94AC-297871967D5E
266
+ X-APPLE-CALENDAR-COLOR:#2CA10B
267
+ BEGIN:VTIMEZONE
268
+ TZID:US/Eastern
269
+ BEGIN:DAYLIGHT
270
+ TZOFFSETFROM:-0500
271
+ TZOFFSETTO:-0400
272
+ DTSTART:20070311T020000
273
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
274
+ TZNAME:EDT
275
+ END:DAYLIGHT
276
+ BEGIN:STANDARD
277
+ TZOFFSETFROM:-0400
278
+ TZOFFSETTO:-0500
279
+ DTSTART:20071104T020000
280
+ RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
281
+ TZNAME:EST
282
+ END:STANDARD
283
+ END:VTIMEZONE
284
+ BEGIN:VEVENT
285
+ SEQUENCE:5
286
+ TRANSP:OPAQUE
287
+ UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
288
+ DTSTART;TZID=US/Eastern:20090224T090000
289
+ DTSTAMP:20090225T000908Z
290
+ SUMMARY:Test Event
291
+ CREATED:20090225T000839Z
292
+ DTEND;TZID=US/Eastern:20090224T100000
293
+ RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
294
+ END:VEVENT
295
+ END:VCALENDAR
296
+ ENDCAL
297
+
298
+ <b>Beware of the initial whitespace in the above example which is for rdoc formatting.</b> The parser does not strip initial whitespace from lines in the file and will fail.
299
+
300
+ As already stated the string argument may be a full icalendar format calendar, or just one or more subcomponents, e.g.
301
+
302
+ RiCal.parse_string("BEGIN:VEVENT\nDTSTART;TZID=US/Eastern:20090224T090000\nSUMMARY:Test Event\nDTEND;TZID=US/Eastern:20090224T100000\nRRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z\nEND:VEVENT")
303
+
304
+ ==== From an Io
305
+ File.open("path/to/file", "r") do |file|
306
+ components = RiCal.parse(file)
307
+ end
308
+
309
+ === Occurrence Enumeration
310
+
311
+ Event, Journal, and Todo components can have recurrences which are defined following the RFC 2445 specification.
312
+ A component with recurrences can enumerate those occurrences.
313
+
314
+ These components have common methods for enumeration which are defined in the RiCal::OccurrenceEnumerator module.
315
+
316
+ ==== Obtaining an array of occurrences
317
+
318
+ To get an array of occurrences, Use the RiCal::OccurrenceEnumerator#occurrences method:
319
+
320
+ event.occurrences
321
+
322
+ This method may fail with an argument error, if the component has an unbounded recurrence definition. This happens
323
+ when one or more of its RRULES don't have a COUNT, or UNTIL part. This may be tested by using the RiCal::OccurrenceEnumerator#bounded? method.
324
+
325
+ In the case of unbounded components, you must either use the :count, or :before options of the RiCal::OccurrenceEnumerator#occurrences method:
326
+
327
+ event.occurrences(:count => 10)
328
+
329
+ or
330
+
331
+ event.occurrences(:before => Date.today >> 1)
332
+
333
+ Alternately, you can use the RiCal::OccurrenceEnumerator#each method,
334
+ or another Enumerable method (RiCal::OccurrenceEnumerator includes Enumerable), and terminate when you wish by breaking out of the block.
335
+
336
+ event.each do |event|
337
+ break if some_termination_condition
338
+ #....
339
+ end
340
+
341
+ == REQUIREMENTS:
342
+
343
+ * RiCal requires that an implementation of TZInfo::Timezone. This requirement may be satisfied by either the TzInfo gem,
344
+ or by a recent(>= 2.2) version of the ActiveSupport gem which is part of Ruby on Rails.
345
+
346
+ == INSTALL:
347
+
348
+ === From RubyForge
349
+
350
+ sudo gem install ri_cal
351
+
352
+ === From github
353
+
354
+ #TODO: publish to github
355
+
356
+ ==== As a Gem
357
+
358
+ #TODO: add the gem source info for github
359
+ sudo gem install ????? --source http://github.com/????
360
+
361
+ ==== From source
362
+
363
+ 1. cd to a directory in which you want to install ri_cal as a subdirectory
364
+ 2. git clone http://github.com/rubyredrick/ri_cal your_install_subdirectory
365
+ 3. cd your_install_directory
366
+ 4. rake spec
367
+ 5. rake install_gem
368
+
369
+
370
+
371
+ == LICENSE:
372
+
373
+ (The MIT License)
374
+
375
+ Copyright (c) 2009 Richard J. DeNatale
376
+
377
+ Permission is hereby granted, free of charge, to any person obtaining
378
+ a copy of this software and associated documentation files (the
379
+ 'Software'), to deal in the Software without restriction, including
380
+ without limitation the rights to use, copy, modify, merge, publish,
381
+ distribute, sublicense, and/or sell copies of the Software, and to
382
+ permit persons to whom the Software is furnished to do so, subject to
383
+ the following conditions:
384
+
385
+ The above copyright notice and this permission notice shall be
386
+ included in all copies or substantial portions of the Software.
387
+
388
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
389
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
390
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
391
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
392
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
393
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
394
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.