awallis-ri_cal 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. data/History.txt +402 -0
  2. data/Manifest.txt +161 -0
  3. data/README.txt +410 -0
  4. data/Rakefile +69 -0
  5. data/VERSION +1 -0
  6. data/bin/ri_cal +8 -0
  7. data/component_attributes/alarm.yml +10 -0
  8. data/component_attributes/calendar.yml +4 -0
  9. data/component_attributes/component_property_defs.yml +180 -0
  10. data/component_attributes/event.yml +45 -0
  11. data/component_attributes/freebusy.yml +16 -0
  12. data/component_attributes/journal.yml +35 -0
  13. data/component_attributes/timezone.yml +3 -0
  14. data/component_attributes/timezone_period.yml +11 -0
  15. data/component_attributes/todo.yml +46 -0
  16. data/copyrights.txt +1 -0
  17. data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
  18. data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
  19. data/docs/incrementers.txt +7 -0
  20. data/docs/rfc2445.pdf +0 -0
  21. data/lib/ri_cal.rb +187 -0
  22. data/lib/ri_cal/component.rb +256 -0
  23. data/lib/ri_cal/component/alarm.rb +19 -0
  24. data/lib/ri_cal/component/calendar.rb +257 -0
  25. data/lib/ri_cal/component/event.rb +58 -0
  26. data/lib/ri_cal/component/freebusy.rb +16 -0
  27. data/lib/ri_cal/component/journal.rb +27 -0
  28. data/lib/ri_cal/component/non_standard.rb +33 -0
  29. data/lib/ri_cal/component/t_z_info_timezone.rb +153 -0
  30. data/lib/ri_cal/component/timezone.rb +197 -0
  31. data/lib/ri_cal/component/timezone/daylight_period.rb +25 -0
  32. data/lib/ri_cal/component/timezone/standard_period.rb +23 -0
  33. data/lib/ri_cal/component/timezone/timezone_period.rb +76 -0
  34. data/lib/ri_cal/component/todo.rb +42 -0
  35. data/lib/ri_cal/core_extensions.rb +11 -0
  36. data/lib/ri_cal/core_extensions/array.rb +7 -0
  37. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  38. data/lib/ri_cal/core_extensions/date.rb +13 -0
  39. data/lib/ri_cal/core_extensions/date/conversions.rb +56 -0
  40. data/lib/ri_cal/core_extensions/date_time.rb +15 -0
  41. data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
  42. data/lib/ri_cal/core_extensions/object.rb +8 -0
  43. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  44. data/lib/ri_cal/core_extensions/string.rb +8 -0
  45. data/lib/ri_cal/core_extensions/string/conversions.rb +57 -0
  46. data/lib/ri_cal/core_extensions/time.rb +14 -0
  47. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  48. data/lib/ri_cal/core_extensions/time/conversions.rb +42 -0
  49. data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
  50. data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +55 -0
  51. data/lib/ri_cal/fast_date_time.rb +234 -0
  52. data/lib/ri_cal/floating_timezone.rb +32 -0
  53. data/lib/ri_cal/invalid_property_value.rb +8 -0
  54. data/lib/ri_cal/invalid_timezone_identifier.rb +20 -0
  55. data/lib/ri_cal/occurrence_enumerator.rb +265 -0
  56. data/lib/ri_cal/occurrence_period.rb +17 -0
  57. data/lib/ri_cal/parser.rb +145 -0
  58. data/lib/ri_cal/properties.rb +12 -0
  59. data/lib/ri_cal/properties/alarm.rb +390 -0
  60. data/lib/ri_cal/properties/calendar.rb +164 -0
  61. data/lib/ri_cal/properties/event.rb +1523 -0
  62. data/lib/ri_cal/properties/freebusy.rb +593 -0
  63. data/lib/ri_cal/properties/journal.rb +1237 -0
  64. data/lib/ri_cal/properties/timezone.rb +150 -0
  65. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  66. data/lib/ri_cal/properties/todo.rb +1559 -0
  67. data/lib/ri_cal/property_value.rb +159 -0
  68. data/lib/ri_cal/property_value/array.rb +27 -0
  69. data/lib/ri_cal/property_value/cal_address.rb +11 -0
  70. data/lib/ri_cal/property_value/date.rb +184 -0
  71. data/lib/ri_cal/property_value/date_time.rb +359 -0
  72. data/lib/ri_cal/property_value/date_time/additive_methods.rb +44 -0
  73. data/lib/ri_cal/property_value/date_time/time_machine.rb +159 -0
  74. data/lib/ri_cal/property_value/date_time/timezone_support.rb +100 -0
  75. data/lib/ri_cal/property_value/duration.rb +110 -0
  76. data/lib/ri_cal/property_value/geo.rb +11 -0
  77. data/lib/ri_cal/property_value/integer.rb +12 -0
  78. data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
  79. data/lib/ri_cal/property_value/period.rb +86 -0
  80. data/lib/ri_cal/property_value/recurrence_rule.rb +154 -0
  81. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +100 -0
  82. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +79 -0
  83. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +148 -0
  84. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +53 -0
  85. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +31 -0
  86. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer.rb +135 -0
  87. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_day_incrementer.rb +86 -0
  88. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_hour_incrementer.rb +31 -0
  89. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_minute_incrementer.rb +32 -0
  90. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_month_incrementer.rb +52 -0
  91. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_monthday_incrementer.rb +31 -0
  92. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_numbered_day_incrementer.rb +38 -0
  93. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_second_incrementer.rb +32 -0
  94. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_weekno_incrementer.rb +69 -0
  95. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_yearday_incrementer.rb +31 -0
  96. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/daily_incrementer.rb +28 -0
  97. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/frequency_incrementer.rb +80 -0
  98. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/hourly_incrementer.rb +23 -0
  99. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/list_incrementer.rb +106 -0
  100. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/minutely_incrementer.rb +23 -0
  101. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/monthly_incrementer.rb +33 -0
  102. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/null_sub_cycle_incrementer.rb +43 -0
  103. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/secondly_incrementer.rb +28 -0
  104. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/weekly_incrementer.rb +37 -0
  105. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/yearly_incrementer.rb +57 -0
  106. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
  107. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +64 -0
  108. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
  109. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +53 -0
  110. data/lib/ri_cal/property_value/recurrence_rule/time_manipulation.rb +42 -0
  111. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
  112. data/lib/ri_cal/property_value/text.rb +44 -0
  113. data/lib/ri_cal/property_value/uri.rb +11 -0
  114. data/lib/ri_cal/property_value/utc_offset.rb +33 -0
  115. data/lib/ri_cal/property_value/zulu_date_time.rb +34 -0
  116. data/lib/ri_cal/required_timezones.rb +55 -0
  117. data/parked_specs/ri_cal/claudio_a_bug_spec.rb +100 -0
  118. data/performance/empty_propval/subject.rb +43 -0
  119. data/performance/paris_eastern/subject.rb +90 -0
  120. data/performance/penultimate_weekday/subject.rb +15 -0
  121. data/performance/psm_big_enum/ical.ics +3171 -0
  122. data/performance/psm_big_enum/subject.rb +16 -0
  123. data/performance/utah_cycling/subject.rb +55 -0
  124. data/ri_cal.gemspec +244 -0
  125. data/script/benchmark_subject +23 -0
  126. data/script/console +10 -0
  127. data/script/destroy +14 -0
  128. data/script/generate +14 -0
  129. data/script/profile_subject +29 -0
  130. data/script/txt2html +71 -0
  131. data/spec/ri_cal/bugreports_spec.rb +276 -0
  132. data/spec/ri_cal/component/alarm_spec.rb +12 -0
  133. data/spec/ri_cal/component/calendar_spec.rb +88 -0
  134. data/spec/ri_cal/component/event_spec.rb +735 -0
  135. data/spec/ri_cal/component/freebusy_spec.rb +12 -0
  136. data/spec/ri_cal/component/journal_spec.rb +37 -0
  137. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +60 -0
  138. data/spec/ri_cal/component/timezone_spec.rb +236 -0
  139. data/spec/ri_cal/component/todo_spec.rb +112 -0
  140. data/spec/ri_cal/component_spec.rb +224 -0
  141. data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
  142. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
  143. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
  144. data/spec/ri_cal/fast_date_time_spec.rb +77 -0
  145. data/spec/ri_cal/inf_loop_spec.rb +78 -0
  146. data/spec/ri_cal/occurrence_enumerator_spec.rb +611 -0
  147. data/spec/ri_cal/parser_spec.rb +337 -0
  148. data/spec/ri_cal/property_value/date_spec.rb +53 -0
  149. data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
  150. data/spec/ri_cal/property_value/duration_spec.rb +126 -0
  151. data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
  152. data/spec/ri_cal/property_value/period_spec.rb +63 -0
  153. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
  154. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
  155. data/spec/ri_cal/property_value/text_spec.rb +25 -0
  156. data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
  157. data/spec/ri_cal/property_value_spec.rb +125 -0
  158. data/spec/ri_cal/required_timezones_spec.rb +67 -0
  159. data/spec/ri_cal_spec.rb +53 -0
  160. data/spec/spec.opts +4 -0
  161. data/spec/spec_helper.rb +50 -0
  162. data/tasks/gem_loader/load_active_support.rb +3 -0
  163. data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
  164. data/tasks/ri_cal.rake +412 -0
  165. data/tasks/spec.rake +102 -0
  166. metadata +255 -0
@@ -0,0 +1,44 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class DateTime
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ # Methods for DateTime which support adding or subtracting another DateTime or Duration
7
+ module AdditiveMethods
8
+ # if end_time is nil => nil
9
+ # otherwise convert end_time to a DateTime and compute the difference
10
+ def duration_until(end_time) # :nodoc:
11
+ end_time && RiCal::PropertyValue::Duration.from_datetimes(timezone_finder, to_datetime, end_time.to_datetime)
12
+ end
13
+
14
+ # Double-dispatch method for subtraction.
15
+ def subtract_from_date_time_value(dtvalue) #:nodoc:
16
+ RiCal::PropertyValue::Duration.from_datetimes(timezone_finder, to_datetime,dtvalue.to_datetime)
17
+ end
18
+
19
+ # Double-dispatch method for addition.
20
+ def add_to_date_time_value(date_time_value) #:nodoc:
21
+ raise ArgumentError.new("Cannot add #{date_time_value} to #{self}")
22
+ end
23
+
24
+ # Return the difference between the receiver and other
25
+ #
26
+ # The parameter other should be either a RiCal::PropertyValue::Duration or a RiCal::PropertyValue::DateTime
27
+ #
28
+ # If other is a Duration, the result will be a DateTime, if it is a DateTime the result will be a Duration
29
+ def -(other)
30
+ other.subtract_from_date_time_value(self)
31
+ end
32
+
33
+ # Return the sum of the receiver and duration
34
+ #
35
+ # The parameter other duration should be a RiCal::PropertyValue::Duration
36
+ #
37
+ # The result will be an RiCal::PropertyValue::DateTime
38
+ def +(duration)
39
+ duration.add_to_date_time_value(self)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,159 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class DateTime
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ # Methods for DateTime which support getting values at different point in time.
7
+ module TimeMachine
8
+
9
+ def advance(options) # :nodoc:
10
+ PropertyValue::DateTime.new(timezone_finder,
11
+ :value => @date_time_value.advance(options),
12
+ :tzid => @tzid,
13
+ :params =>(params ? params.dup : nil)
14
+ )
15
+ end
16
+
17
+ def change(options) # :nodoc:
18
+ PropertyValue::DateTime.new(timezone_finder,
19
+ :value => @date_time_value.change(options),
20
+ :tzid => @tzid,
21
+ :params => (params ? params.dup : nil)
22
+ )
23
+ end
24
+
25
+ def change_sec(new_sec) #:nodoc:
26
+ change(:sec => new_sec)
27
+ end
28
+
29
+ def change_min(new_min) #:nodoc:
30
+ change(:min => new_min)
31
+ end
32
+
33
+ def change_hour(new_hour) #:nodoc:
34
+ change(:hour => new_hour)
35
+ end
36
+
37
+ def change_day(new_day) #:nodoc:
38
+ change(:day => new_day)
39
+ end
40
+
41
+ def change_month(new_month) #:nodoc:
42
+ change(:month => new_month)
43
+ end
44
+
45
+ def change_year(new_year) #:nodoc:
46
+ change(:year => new_year)
47
+ end
48
+
49
+ # Return a DATE-TIME property representing the receiver on a different day (if necessary) so that
50
+ # the result is within the 7 days starting with date
51
+ def in_week_starting?(date)
52
+ wkst_jd = date.jd
53
+ @date_time_value.jd.between?(wkst_jd, wkst_jd + 6)
54
+ end
55
+
56
+ # Return a DATE-TIME property representing the receiver on a different day (if necessary) so that
57
+ # the result is the first day of the ISO week starting on the wkst day containing the receiver.
58
+ def at_start_of_week_with_wkst(wkst)
59
+ date = @date_time_value.start_of_week_with_wkst(wkst)
60
+ change(:year => date.year, :month => date.month, :day => date.day)
61
+ end
62
+ # Return a DATE_TIME value representing the first second of the minute containing the receiver
63
+ def start_of_minute
64
+ change(:sec => 0)
65
+ end
66
+
67
+ # Return a DATE_TIME value representing the last second of the minute containing the receiver
68
+ def end_of_minute
69
+ change(:sec => 59)
70
+ end
71
+
72
+ # Return a DATE_TIME value representing the first second of the hour containing the receiver
73
+ def start_of_hour
74
+ change(:min => 0, :sec => 0)
75
+ end
76
+
77
+ # Return a DATE_TIME value representing the last second of the hour containing the receiver
78
+ def end_of_hour
79
+ change(:min => 59, :sec => 59)
80
+ end
81
+
82
+ # Return a DATE_TIME value representing the first second of the day containing the receiver
83
+ def start_of_day
84
+ change(:hour => 0, :min => 0, :sec => 0)
85
+ end
86
+
87
+ # Return a DATE_TIME value representing the last second of the day containing the receiver
88
+ def end_of_day
89
+ change(:hour => 23, :min => 59, :sec => 59)
90
+ end
91
+
92
+ # Return a Ruby Date representing the first day of the ISO week starting with wkst containing the receiver
93
+ def start_of_week_with_wkst(wkst)
94
+ @date_time_value.start_of_week_with_wkst(wkst)
95
+ end
96
+
97
+ # Return a DATE_TIME value representing the last second of the ISO week starting with wkst containing the receiver
98
+ def end_of_week_with_wkst(wkst)
99
+ date = at_start_of_week_with_wkst(wkst).advance(:days => 6).end_of_day
100
+ end
101
+
102
+ # Return a DATE_TIME value representing the first second of the month containing the receiver
103
+ def start_of_month
104
+ change(:day => 1, :hour => 0, :min => 0, :sec => 0)
105
+ end
106
+
107
+ # Return a DATE_TIME value representing the last second of the month containing the receiver
108
+ def end_of_month
109
+ change(:day => days_in_month, :hour => 23, :min => 59, :sec => 59)
110
+ end
111
+
112
+ # Return a DATE_TIME value representing the first second of the month containing the receiver
113
+ def start_of_year
114
+ change(:month => 1, :day => 1, :hour => 0, :min => 0, :sec => 0)
115
+ end
116
+
117
+ # Return a DATE_TIME value representing the last second of the month containing the receiver
118
+ def end_of_year
119
+ change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59)
120
+ end
121
+
122
+ # Return a DATE_TIME value representing the same time on the first day of the ISO year with weeks
123
+ # starting on wkst containing the receiver
124
+ def at_start_of_iso_year(wkst)
125
+ start_of_year = @date_time_value.iso_year_start(wkst)
126
+ change(:year => start_of_year.year, :month => start_of_year.month, :day => start_of_year.day)
127
+ end
128
+
129
+ # Return a DATE_TIME value representing the same time on the last day of the ISO year with weeks
130
+ # starting on wkst containing the receiver
131
+ def at_end_of_iso_year(wkst)
132
+ num_weeks = @date_time_value.iso_weeks_in_year(wkst)
133
+ at_start_of_iso_year(wkst).advance(:weeks => (num_weeks - 1), :days => 6)
134
+ end
135
+
136
+ # Return a DATE_TIME value representing the same time on the first day of the ISO year with weeks
137
+ # starting on wkst after the ISO year containing the receiver
138
+ def at_start_of_next_iso_year(wkst)
139
+ num_weeks = @date_time_value.iso_weeks_in_year(wkst)
140
+ at_start_of_iso_year(wkst).advance(:weeks => num_weeks)
141
+ end
142
+
143
+ # Return a DATE_TIME value representing the last second of the last day of the ISO year with weeks
144
+ # starting on wkst containing the receiver
145
+ def end_of_iso_year(wkst)
146
+ at_end_of_iso_year(wkst).end_of_day
147
+ end
148
+
149
+ # Return a DATE-TIME representing the same time, on the same day of the month in month.
150
+ # If the month of the receiver has more days than the target month the last day of the target month
151
+ # will be used.
152
+ def in_month(month)
153
+ first = change(:day => 1, :month => month)
154
+ first.change(:day => [first.days_in_month, day].min)
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,100 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ class DateTime
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ # Time zone related methods for DateTime
7
+ module TimezoneSupport
8
+ # Return the timezone id of the receiver, or nil if it is a floating time
9
+ def tzid
10
+ @tzid == :floating ? nil : @tzid
11
+ end
12
+
13
+ def tzid=(timezone_id) #:nodoc:
14
+ timezone_id = default_tzid if timezone_id == :default
15
+ @tzid = timezone_id
16
+ reset_cached_values
17
+ end
18
+
19
+ def reset_cached_values #:nodoc:
20
+ @timezone = @utc = @rational_tz_offset = nil
21
+ end
22
+
23
+ def find_timezone #:nodoc:
24
+ if @tzid == :floating
25
+ FloatingTimezone
26
+ else
27
+ timezone_finder.find_timezone(@tzid)
28
+ end
29
+ end
30
+
31
+ def timezone #:nodoc:
32
+ @timezone ||= find_timezone
33
+ end
34
+
35
+ # Determine if the receiver has a local time zone, i.e. it is not a floating time or a UTC time
36
+ def has_local_timezone?
37
+ tzid && tzid.upcase != "UTC"
38
+ end
39
+
40
+ # Return the receiver if it has a floating time zone already,
41
+ # otherwise return a DATETIME property with the same time as the receiver but with a floating time zone
42
+ def with_floating_timezone
43
+ if @tzid == nil
44
+ self
45
+ else
46
+ @date_time_value.with_floating_timezone.to_ri_cal_date_time_value
47
+ end
48
+ end
49
+
50
+ # Returns a instance that represents the time in UTC.
51
+ def utc
52
+ if has_local_timezone?
53
+ @utc ||= timezone.local_to_utc(self)
54
+ else # Already local or a floating time
55
+ self
56
+ end
57
+ end
58
+
59
+ def rational_tz_offset #:nodoc:
60
+ if has_local_timezone?
61
+ @rational_tz_offset ||= timezone.rational_utc_offset(@date_time_value.to_datetime)
62
+ else
63
+ @rational_tz_offset ||= RiCal.RationalOffset[0]
64
+ end
65
+ end
66
+
67
+ # Predicate indicating whether or not the instance represents a ZULU time
68
+ def utc?
69
+ tzid == "UTC"
70
+ end
71
+
72
+ # Predicate indicating whether or not the instance represents a floating time
73
+ def floating?
74
+ tzid.nil?
75
+ end
76
+
77
+ def has_valid_tzinfo_tzid? #:nodoc:
78
+ if tzid && tzid != :floating
79
+ TZInfo::Timezone.get(tzid) rescue false
80
+ else
81
+ false
82
+ end
83
+ end
84
+
85
+ # Returns the simultaneous time in the specified zone.
86
+ def in_time_zone(new_zone)
87
+ new_zone = timezone_finder.find_timezone(new_zone)
88
+ return self if tzid == new_zone.identifier
89
+ if has_local_timezone?
90
+ new_zone.utc_to_local(utc)
91
+ elsif utc?
92
+ new_zone.utc_to_local(self)
93
+ else # Floating time
94
+ DateTime.new(timezone_finder, :value => @date_time_value, :tzid => new_zone.identifier)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,110 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
4
+ #
5
+ # RiCal::PropertyValue::CalAddress represents an icalendar Duration property value
6
+ # which is defined in
7
+ # rfc 2445 section 4.3.6 p 37
8
+ class Duration < PropertyValue
9
+
10
+ def self.value_part(unit, diff) # :nodoc:
11
+ (diff == 0) ? nil : "#{diff}#{unit}"
12
+ end
13
+
14
+ def self.from_datetimes(parent, start, finish, sign='+') # :nodoc:
15
+ if start > finish
16
+ from_datetimes(self, finish, start, '-')
17
+ else
18
+ diff = finish - start
19
+ days_diff = diff.to_i
20
+ hours = (diff - days_diff) * 24
21
+ hour_diff = hours.to_i
22
+ minutes = (hours - hour_diff) * 60
23
+ min_diff = minutes.to_i
24
+ seconds = (minutes - min_diff) * 60
25
+ sec_diff = seconds.to_i
26
+
27
+ day_part = value_part('D',days_diff)
28
+ hour_part = value_part('H', hour_diff)
29
+ min_part = value_part('M', min_diff)
30
+ sec_part = value_part('S', sec_diff)
31
+ t_part = (hour_diff.abs + min_diff.abs + sec_diff.abs) == 0 ? "" : "T"
32
+ new(parent, :value => "#{sign}P#{day_part}#{t_part}#{hour_part}#{min_part}#{sec_part}")
33
+ end
34
+ end
35
+
36
+ def self.convert(parent, ruby_object) # :nodoc:
37
+ ruby_object.to_ri_cal_duration_value
38
+ end
39
+
40
+ def value=(string) # :nodoc:
41
+ super
42
+ match = /([+-])?P(.*)$/.match(string)
43
+ @days = @hours = @minutes = @seconds = @weeks = 0
44
+ if match
45
+ @sign = match[1] == '-' ? -1 : 1
46
+ match[2].scan(/(\d+)([DHMSW])/) do |digits, unit|
47
+ number = digits.to_i
48
+ case unit
49
+ when 'D'
50
+ @days = number
51
+ when 'H'
52
+ @hours = number
53
+ when 'M'
54
+ @minutes = number
55
+ when 'S'
56
+ @seconds = number
57
+ when 'W'
58
+ @weeks = number
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ def self.valid_string?(string) #:nodoc:
65
+ string =~ /^[+-]?P((\d+D)(T((\d+)[HMS])+)?)|(T((\d+)[HMS])+)|(\d+W)$/
66
+ end
67
+
68
+ def days # :nodoc:
69
+ @days * @sign
70
+ end
71
+
72
+ def weeks # :nodoc:
73
+ @weeks * @sign
74
+ end
75
+
76
+ def hours # :nodoc:
77
+ @hours * @sign
78
+ end
79
+
80
+ def minutes # :nodoc:
81
+ @minutes * @sign
82
+ end
83
+
84
+ def seconds # :nodoc:
85
+ @seconds * @sign
86
+ end
87
+
88
+ # Determine whether another object is an equivalent RiCal::PropertyValue::Duration
89
+ def ==(other)
90
+ other.kind_of?(PropertyValue::Duration) && value == other.value
91
+ end
92
+
93
+ # Returns the receiver
94
+ def to_ri_cal_duration_value
95
+ self
96
+ end
97
+
98
+ # Double-dispatch method to support RiCal::PropertyValue::DateTime.-
99
+ def subtract_from_date_time_value(date_time_value)
100
+ date_time_value.advance(:weeks => -weeks, :days => -days, :hours => -hours, :minutes => -minutes, :seconds => -seconds)
101
+ end
102
+
103
+ # Double-dispatch method to support RiCal::PropertyValue::DateTime.+
104
+ def add_to_date_time_value(date_time_value)
105
+ date_time_value.advance(:weeks => weeks, :days => days, :hours => hours, :minutes => minutes, :seconds => seconds)
106
+ end
107
+
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,11 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
4
+ #
5
+ # RiCal::PropertyValue::CalAddress represents an icalendar Duration property value
6
+ # which is defined in
7
+ # rfc 2445 section 4.8.1.6 pp 82-83
8
+ class Geo < PropertyValue
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
4
+ #
5
+ class Integer < PropertyValue # :nodoc:
6
+
7
+ def value=(string)
8
+ @value = string.to_i
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,144 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ # OccurrenceList is used to represent the value of an RDATE or EXDATE property.
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class OccurrenceList < Array
7
+ attr_accessor :tzid #:nodoc:
8
+
9
+ class Enumerator # :nodoc:
10
+
11
+ attr_accessor :default_duration, :occurrence_list
12
+
13
+ # TODO: the component parameter should always be the parent
14
+ def initialize(occurrences, component) # :nodoc:
15
+ self.occurrence_list = occurrences
16
+ self.default_duration = component.default_duration
17
+ @index = 0
18
+ end
19
+
20
+ def bounded?
21
+ true
22
+ end
23
+
24
+ def empty?
25
+ occurrence_list.empty?
26
+ end
27
+
28
+ def next_occurrence
29
+ if @index < occurrence_list.length
30
+ result = occurrence_list[@index].occurrence_period(default_duration)
31
+ @index += 1
32
+ result
33
+ else
34
+ nil
35
+ end
36
+ end
37
+ end
38
+
39
+ def initialize(timezone_finder, options={}) # :nodoc:
40
+ super
41
+ validate_elements
42
+ end
43
+
44
+ def self.convert(timezone_finder, *ruby_objects) # :nodoc:
45
+ # ruby_objects = [ruby_objects] unless Array === ruby_objects
46
+ source_elements = ruby_objects.inject([]) { |se, element|
47
+ if String === element
48
+ element.split(",").each {|str| se << str}
49
+ else
50
+ se << element
51
+ end
52
+ se
53
+ }
54
+ new(timezone_finder, :source_elements => source_elements )
55
+ end
56
+
57
+ def values_to_elements(values) # :nodoc:
58
+ values.map {|val| val.to_ri_cal_occurrence_list_value(self)}
59
+ end
60
+
61
+ def tzid_from_source_elements # :nodoc:
62
+ if @source_elements && String === (first_source = @source_elements.first)
63
+ probe = first_source.to_ri_cal_occurrence_list_value rescue nil
64
+ unless probe
65
+ return @source_elements.shift
66
+ end
67
+ end
68
+ nil
69
+ end
70
+
71
+ def tzid_conflict(element_tzid) # :nodoc:
72
+ element_tzid && tzid != element_tzid
73
+ end
74
+
75
+ def validate_elements # :nodoc:
76
+ if @source_elements
77
+ self.tzid = tzid_from_source_elements
78
+ @elements = values_to_elements(@source_elements)
79
+ @value = @elements.map {|prop| prop.value}
80
+ else
81
+ @elements = values_to_elements(@value)
82
+ self.tzid = params['TZID']
83
+ end
84
+ # if the tzid wasn't set by the parameters
85
+ self.tzid ||= @elements.map {|element| element.tzid}.find {|id| id}
86
+ @elements.each do |element|
87
+ raise InvalidPropertyValue.new("Mixed timezones are not allowed in an occurrence list") if tzid_conflict(element.tzid)
88
+ element.tzid = tzid
89
+ end
90
+ end
91
+
92
+ def has_local_timezone? # :nodoc:
93
+ tzid && tzid != 'UTC'
94
+ end
95
+
96
+ def visible_params # :nodoc:
97
+ result = params.dup
98
+ if has_local_timezone?
99
+ result['TZID'] = tzid
100
+ else
101
+ result.delete('TZID')
102
+ end
103
+ result
104
+ end
105
+
106
+ def value # :nodoc:
107
+ @elements.map {|element| element.value}.join(",")
108
+ end
109
+
110
+ # Return an array of the occurrences within the list
111
+ def ruby_value
112
+ @elements.map {|prop| prop.ruby_value}
113
+ end
114
+ end
115
+
116
+ attr_accessor :elements, :source_elements #:nodoc:
117
+ private :elements, :elements=, :source_elements=, :source_elements
118
+
119
+ def for_parent(parent) #:nodoc:
120
+ if timezone_finder.nil?
121
+ @timezone_finder = parent
122
+ self
123
+ elsif timezone_finder == parent
124
+ self
125
+ else
126
+ OccurrenceList.new(parent, :value => value)
127
+ end
128
+ end
129
+
130
+ # Return an enumerator which can produce the elements of the occurrence list
131
+ def enumerator(component) # :nodoc:
132
+ OccurrenceList::Enumerator.new(@elements, component)
133
+ end
134
+
135
+ def add_date_times_to(required_timezones) #:nodoc:
136
+ if @elements
137
+ @elements.each do | occurrence |
138
+ occurrence.add_date_times_to(required_timezones)
139
+ end
140
+ end
141
+ end
142
+
143
+ end
144
+ end