ri_cal 0.5.0

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 (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,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,181 @@
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
+ def compute_change(d, options) # :nodoc:
9
+ ::DateTime.civil(
10
+ options[:year] || d.year,
11
+ options[:month] || d.month,
12
+ options[:day] || d.day,
13
+ options[:hour] || d.hour,
14
+ options[:min] || (options[:hour] ? 0 : d.min),
15
+ options[:sec] || ((options[:hour] || options[:min]) ? 0 : d.sec),
16
+ options[:offset] || d.offset,
17
+ options[:start] || d.start
18
+ )
19
+ end
20
+
21
+ def compute_advance(d, options) # :nodoc:
22
+ d = d >> options[:years] * 12 if options[:years]
23
+ d = d >> options[:months] if options[:months]
24
+ d = d + options[:weeks] * 7 if options[:weeks]
25
+ d = d + options[:days] if options[:days]
26
+ datetime_advanced_by_date = compute_change(@date_time_value, :year => d.year, :month => d.month, :day => d.day)
27
+ seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
28
+ seconds_to_advance == 0 ? datetime_advanced_by_date : datetime_advanced_by_date + Rational(seconds_to_advance.round, 86400)
29
+ end
30
+
31
+ def advance(options) # :nodoc:
32
+ PropertyValue::DateTime.new(timezone_finder,
33
+ :value => compute_advance(@date_time_value, options),
34
+ :tzid => @tzid,
35
+ :params =>(params ? params.dup : nil)
36
+ )
37
+ end
38
+
39
+ def change(options) # :nodoc:
40
+ PropertyValue::DateTime.new(timezone_finder,
41
+ :value => compute_change(@date_time_value, options),
42
+ :tzid => @tzid,
43
+ :params => (params ? params.dup : nil)
44
+ )
45
+ end
46
+
47
+ def change_sec(new_sec) #:nodoc:
48
+ PropertyValue::DateTime.civil(self.year, self.month, self.day, self.hour, self.min, sec, self.offset, self.start, params)
49
+ end
50
+
51
+ def change_min(new_min) #:nodoc:
52
+ PropertyValue::DateTime.civil(self.year, self.month, self.day, self.hour, new_min, self.sec, self.offset, self.start, params)
53
+ end
54
+
55
+ def change_hour(new_hour) #:nodoc:
56
+ PropertyValue::DateTime.civil(self.year, self.month, self.day, new_hour, self.min, self.sec, self.offset, self.start, params)
57
+ end
58
+
59
+ def change_day(new_day) #:nodoc:
60
+ PropertyValue::DateTime.civil(self.year, self.month, new_day, self.hour, self.min, self.sec, self.offset, self.start, params)
61
+ end
62
+
63
+ def change_month(new_month) #:nodoc:
64
+ PropertyValue::DateTime.civil(self.year, new_month, self.day, self.hour, self.min, self.sec, self.offset, self.start, params)
65
+ end
66
+
67
+ def change_year(new_year) #:nodoc:
68
+ PropertyValue::DateTime.civil(new_year, self.month, self.day, self.hour, self.min, self.sec, self.offset, self.start, params)
69
+ end
70
+
71
+ # Return a DATE-TIME property representing the receiver on a different day (if necessary) so that
72
+ # the result is within the 7 days starting with date
73
+ def in_week_starting?(date)
74
+ wkst_jd = date.jd
75
+ @date_time_value.jd.between?(wkst_jd, wkst_jd + 6)
76
+ end
77
+
78
+ # Return a DATE-TIME property representing the receiver on a different day (if necessary) so that
79
+ # the result is the first day of the ISO week starting on the wkst day containing the receiver.
80
+ def at_start_of_week_with_wkst(wkst)
81
+ date = @date_time_value.start_of_week_with_wkst(wkst)
82
+ change(:year => date.year, :month => date.month, :day => date.day)
83
+ end
84
+ # Return a DATE_TIME value representing the first second of the minute containing the receiver
85
+ def start_of_minute
86
+ change(:sec => 0)
87
+ end
88
+
89
+ # Return a DATE_TIME value representing the last second of the minute containing the receiver
90
+ def end_of_minute
91
+ change(:sec => 59)
92
+ end
93
+
94
+ # Return a DATE_TIME value representing the first second of the hour containing the receiver
95
+ def start_of_hour
96
+ change(:min => 0, :sec => 0)
97
+ end
98
+
99
+ # Return a DATE_TIME value representing the last second of the hour containing the receiver
100
+ def end_of_hour
101
+ change(:min => 59, :sec => 59)
102
+ end
103
+
104
+ # Return a DATE_TIME value representing the first second of the day containing the receiver
105
+ def start_of_day
106
+ change(:hour => 0, :min => 0, :sec => 0)
107
+ end
108
+
109
+ # Return a DATE_TIME value representing the last second of the day containing the receiver
110
+ def end_of_day
111
+ change(:hour => 23, :min => 59, :sec => 59)
112
+ end
113
+
114
+ # Return a Ruby Date representing the first day of the ISO week starting with wkst containing the receiver
115
+ def start_of_week_with_wkst(wkst)
116
+ @date_time_value.start_of_week_with_wkst(wkst)
117
+ end
118
+
119
+ # Return a DATE_TIME value representing the last second of the ISO week starting with wkst containing the receiver
120
+ def end_of_week_with_wkst(wkst)
121
+ date = at_start_of_week_with_wkst(wkst).advance(:days => 6).end_of_day
122
+ end
123
+
124
+ # Return a DATE_TIME value representing the first second of the month containing the receiver
125
+ def start_of_month
126
+ change(:day => 1, :hour => 0, :min => 0, :sec => 0)
127
+ end
128
+
129
+ # Return a DATE_TIME value representing the last second of the month containing the receiver
130
+ def end_of_month
131
+ change(:day => days_in_month, :hour => 23, :min => 59, :sec => 59)
132
+ end
133
+
134
+ # Return a DATE_TIME value representing the first second of the month containing the receiver
135
+ def start_of_year
136
+ change(:month => 1, :day => 1, :hour => 0, :min => 0, :sec => 0)
137
+ end
138
+
139
+ # Return a DATE_TIME value representing the last second of the month containing the receiver
140
+ def end_of_year
141
+ change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59)
142
+ end
143
+
144
+ # Return a DATE_TIME value representing the same time on the first day of the ISO year with weeks
145
+ # starting on wkst containing the receiver
146
+ def at_start_of_iso_year(wkst)
147
+ start_of_year = @date_time_value.iso_year_start(wkst)
148
+ change(:year => start_of_year.year, :month => start_of_year.month, :day => start_of_year.day)
149
+ end
150
+
151
+ # Return a DATE_TIME value representing the same time on the last day of the ISO year with weeks
152
+ # starting on wkst containing the receiver
153
+ def at_end_of_iso_year(wkst)
154
+ num_weeks = @date_time_value.iso_weeks_in_year(wkst)
155
+ at_start_of_iso_year(wkst).advance(:weeks => (num_weeks - 1), :days => 6)
156
+ end
157
+
158
+ # Return a DATE_TIME value representing the same time on the first day of the ISO year with weeks
159
+ # starting on wkst after the ISO year containing the receiver
160
+ def at_start_of_next_iso_year(wkst)
161
+ num_weeks = @date_time_value.iso_weeks_in_year(wkst)
162
+ at_start_of_iso_year(wkst).advance(:weeks => num_weeks)
163
+ end
164
+
165
+ # Return a DATE_TIME value representing the last second of the last day of the ISO year with weeks
166
+ # starting on wkst containing the receiver
167
+ def end_of_iso_year(wkst)
168
+ at_end_of_iso_year(wkst).end_of_day
169
+ end
170
+
171
+ # Return a DATE-TIME representing the same time, on the same day of the month in month.
172
+ # If the month of the receiver has more days than the target month the last day of the target month
173
+ # will be used.
174
+ def in_month(month)
175
+ first = change(:day => 1, :month => month)
176
+ first.change(:day => [first.days_in_month, day].min)
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,96 @@
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
+ @timezone = nil
17
+ end
18
+
19
+ def find_timezone #:nodoc:
20
+ if @tzid == :floating
21
+ FloatingTimezone
22
+ else
23
+ timezone_finder.find_timezone(@tzid)
24
+ end
25
+ end
26
+
27
+ def timezone #:nodoc:
28
+ @timezone ||= find_timezone
29
+ end
30
+
31
+ # Determine if the receiver has a local time zone, i.e. it is not a floating time or a UTC time
32
+ def has_local_timezone?
33
+ tzid && tzid.upcase != "UTC"
34
+ end
35
+
36
+ # Return the receiver if it has a floating time zone already,
37
+ # otherwise return a DATETIME property with the same time as the receiver but with a floating time zone
38
+ def with_floating_timezone
39
+ if @tzid == nil
40
+ self
41
+ else
42
+ @date_time_value.with_floating_timezone.to_ri_cal_date_time_value
43
+ end
44
+ end
45
+
46
+ # Returns a instance that represents the time in UTC.
47
+ def utc
48
+ if has_local_timezone?
49
+ timezone.local_to_utc(self)
50
+ else # Already local or a floating time
51
+ self
52
+ end
53
+ end
54
+
55
+ def rational_tz_offset #:nodoc:
56
+ if has_local_timezone?
57
+ timezone.rational_utc_offset(@date_time_value)
58
+ else
59
+ Rational(0,24)
60
+ end
61
+ end
62
+
63
+ # Predicate indicating whether or not the instance represents a ZULU time
64
+ def utc?
65
+ tzid == "UTC"
66
+ end
67
+
68
+ # Predicate indicating whether or not the instance represents a floating time
69
+ def floating?
70
+ tzid.nil?
71
+ end
72
+
73
+ def has_valid_tzinfo_tzid? #:nodoc:
74
+ if tzid && tzid != :floating
75
+ TZInfo::Timezone.get(tzid) rescue false
76
+ else
77
+ false
78
+ end
79
+ end
80
+
81
+ # Returns the simultaneous time in the specified zone.
82
+ def in_time_zone(new_zone)
83
+ new_zone = timezone_finder.find_timezone(new_zone)
84
+ return self if tzid == new_zone.identifier
85
+ if has_local_timezone?
86
+ new_zone.utc_to_local(utc)
87
+ elsif utc?
88
+ new_zone.utc_to_local(self)
89
+ else # Floating time
90
+ DateTime.new(timezone_finder, :value => @date_time_value, :tzid => new_zone.identifier)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ 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.for_parent(parent)
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+)[DHMSW])+$/
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