rubyredrick-ri_cal 0.0.2 → 0.0.3

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 (97) hide show
  1. data/History.txt +19 -2
  2. data/Manifest.txt +6 -3
  3. data/README.txt +130 -44
  4. data/Rakefile +1 -1
  5. data/copyrights.txt +1 -2
  6. data/lib/ri_cal/component/alarm.rb +1 -2
  7. data/lib/ri_cal/component/calendar.rb +25 -9
  8. data/lib/ri_cal/component/event.rb +1 -2
  9. data/lib/ri_cal/component/freebusy.rb +1 -2
  10. data/lib/ri_cal/component/journal.rb +1 -2
  11. data/lib/ri_cal/component/t_z_info_timezone.rb +1 -2
  12. data/lib/ri_cal/component/timezone/daylight_period.rb +1 -2
  13. data/lib/ri_cal/component/timezone/standard_period.rb +1 -2
  14. data/lib/ri_cal/component/timezone/timezone_period.rb +1 -2
  15. data/lib/ri_cal/component/timezone.rb +5 -2
  16. data/lib/ri_cal/component.rb +22 -7
  17. data/lib/ri_cal/core_extensions/date/conversions.rb +8 -7
  18. data/lib/ri_cal/core_extensions/date_time.rb +4 -2
  19. data/lib/ri_cal/core_extensions/object/conversions.rb +1 -1
  20. data/lib/ri_cal/core_extensions/string/conversions.rb +37 -6
  21. data/lib/ri_cal/core_extensions/time/conversions.rb +11 -7
  22. data/lib/ri_cal/core_extensions/time/tzid_access.rb +37 -0
  23. data/lib/ri_cal/core_extensions/time.rb +3 -1
  24. data/lib/ri_cal/floating_timezone.rb +32 -0
  25. data/lib/ri_cal/invalid_property_value.rb +8 -0
  26. data/lib/ri_cal/invalid_timezone_identifer.rb +2 -2
  27. data/lib/ri_cal/occurrence_enumerator.rb +5 -3
  28. data/lib/ri_cal/parser.rb +8 -8
  29. data/lib/ri_cal/properties/alarm.rb +8 -8
  30. data/lib/ri_cal/properties/event.rb +60 -60
  31. data/lib/ri_cal/properties/freebusy.rb +16 -16
  32. data/lib/ri_cal/properties/journal.rb +58 -58
  33. data/lib/ri_cal/properties/timezone_period.rb +23 -23
  34. data/lib/ri_cal/properties/todo.rb +63 -64
  35. data/lib/ri_cal/property_value/array.rb +10 -2
  36. data/lib/ri_cal/property_value/cal_address.rb +1 -2
  37. data/lib/ri_cal/property_value/date.rb +15 -3
  38. data/lib/ri_cal/property_value/date_time/additive_methods.rb +34 -33
  39. data/lib/ri_cal/property_value/date_time/time_machine.rb +175 -174
  40. data/lib/ri_cal/property_value/date_time/timezone_support.rb +70 -52
  41. data/lib/ri_cal/property_value/date_time.rb +47 -77
  42. data/lib/ri_cal/property_value/duration.rb +6 -3
  43. data/lib/ri_cal/property_value/geo.rb +1 -2
  44. data/lib/ri_cal/property_value/integer.rb +1 -2
  45. data/lib/ri_cal/property_value/occurrence_list.rb +79 -26
  46. data/lib/ri_cal/property_value/period.rb +23 -3
  47. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +1 -2
  48. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +1 -2
  49. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +1 -2
  50. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +1 -2
  51. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +1 -2
  52. data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +1 -2
  53. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +1 -2
  54. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +1 -2
  55. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +1 -2
  56. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +1 -2
  57. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +1 -2
  58. data/lib/ri_cal/property_value/recurrence_rule.rb +3 -4
  59. data/lib/ri_cal/property_value/text.rb +1 -2
  60. data/lib/ri_cal/property_value/uri.rb +1 -2
  61. data/lib/ri_cal/property_value/utc_offset.rb +1 -2
  62. data/lib/ri_cal/property_value.rb +42 -11
  63. data/lib/ri_cal/required_timezones.rb +1 -2
  64. data/lib/ri_cal.rb +1 -2
  65. data/ri_cal.gemspec +6 -4
  66. data/spec/ri_cal/component/alarm_spec.rb +1 -2
  67. data/spec/ri_cal/component/calendar_spec.rb +1 -2
  68. data/spec/ri_cal/component/event_spec.rb +168 -13
  69. data/spec/ri_cal/component/freebusy_spec.rb +1 -2
  70. data/spec/ri_cal/component/journal_spec.rb +1 -2
  71. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +1 -2
  72. data/spec/ri_cal/component/timezone_spec.rb +1 -2
  73. data/spec/ri_cal/component/todo_spec.rb +4 -5
  74. data/spec/ri_cal/component_spec.rb +30 -18
  75. data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
  76. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +1 -2
  77. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +1 -2
  78. data/spec/ri_cal/occurrence_enumerator_spec.rb +23 -2
  79. data/spec/ri_cal/parser_spec.rb +6 -7
  80. data/spec/ri_cal/property_value/date_spec.rb +1 -2
  81. data/spec/ri_cal/property_value/date_time_spec.rb +54 -119
  82. data/spec/ri_cal/property_value/duration_spec.rb +12 -2
  83. data/spec/ri_cal/property_value/occurrence_list_spec.rb +67 -0
  84. data/spec/ri_cal/property_value/period_spec.rb +1 -2
  85. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +1 -2
  86. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1 -2
  87. data/spec/ri_cal/property_value/text_spec.rb +1 -2
  88. data/spec/ri_cal/property_value/utc_offset_spec.rb +1 -2
  89. data/spec/ri_cal/property_value_spec.rb +19 -8
  90. data/spec/ri_cal/required_timezones_spec.rb +1 -2
  91. data/spec/ri_cal_spec.rb +1 -2
  92. data/spec/spec_helper.rb +2 -7
  93. data/tasks/ri_cal.rake +20 -13
  94. data/tasks/spec.rake +1 -1
  95. metadata +8 -5
  96. data/lib/ri_cal/core_extensions/date_time/conversions.rb +0 -27
  97. data/lib/ri_cal/time_with_floating_timezone.rb +0 -59
@@ -4,19 +4,50 @@ module RiCal
4
4
  #- ©2009 Rick DeNatale
5
5
  #- All rights reserved. Refer to the file README.txt for the license
6
6
  #
7
- module Conversions
7
+ module Conversions #:nodoc:
8
8
  # Parse the receiver as an RiCal::PropertyValue::DateTime
9
- def to_ri_cal_date_time_value
10
- RiCal::PropertyValue::DateTime.from_string(self)
9
+ def to_ri_cal_date_time_value(timezone_finder = nil)
10
+ params, value = *Parser.params_and_value(self, :no_leading_semicolon)
11
+ if PropertyValue::DateTime.valid_string?(value)
12
+ PropertyValue::DateTime.new(timezone_finder, :params => params, :value => value)
13
+ else
14
+ raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 date-time")
15
+ end
11
16
  end
17
+
12
18
 
13
- alias_method :to_ri_cal_date_or_date_time_value, :to_ri_cal_date_time_value
19
+ def to_ri_cal_date_or_date_time_value(timezone_finder = nil)
20
+ params, value = *Parser.params_and_value(self, :no_leading_semicolon)
21
+ if PropertyValue::DateTime.valid_string?(value) || PropertyValue::Date.valid_string?(value)
22
+ PropertyValue.date_or_date_time(timezone_finder, :params => params, :value => value)
23
+ else
24
+ raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 date or date-time")
25
+ end
26
+ end
14
27
 
15
28
  # Parse the receiver as an RiCal::PropertyValue::DurationValue
16
- def to_ri_cal_duration_value
17
- RiCal::PropertyValue::Duration.from_string(self)
29
+ def to_ri_cal_duration_value(timezone_finder = nil)
30
+ params, value = *Parser.params_and_value(self)
31
+ if PropertyValue::Duration.valid_string?(value)
32
+ PropertyValue::Duration.new(timezone_finder, :params => params, :value => value)
33
+ else
34
+ raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 duration")
35
+ end
18
36
  end
19
37
 
38
+ def to_ri_cal_occurrence_list_value(timezone_finder = nil)
39
+ params, value = *Parser.params_and_value(self, :no_leading_semicolon)
40
+ if PropertyValue::DateTime.valid_string?(value)
41
+ PropertyValue::DateTime.new(timezone_finder, :params => params, :value => value)
42
+ elsif PropertyValue::Date.valid_string?(value)
43
+ PropertyValue::Date.new(timezone_finder, :params => params, :value => value)
44
+ elsif PropertyValue::Period.valid_string?(value)
45
+ PropertyValue::Period.new(timezone_finder, :params => params, :value => value)
46
+ else
47
+ raise "Invalid value for occurrence list #{self.inspect}"
48
+ end
49
+ end
50
+
20
51
  # code stolen from ActiveSupport Gem
21
52
  unless ::String.instance_methods.include?("camelize")
22
53
  # Convert the receiver to camelized form
@@ -6,20 +6,24 @@ module RiCal
6
6
  #
7
7
  module Conversions
8
8
  # Return an RiCal::PropertyValue::DateTime representing the receiver
9
- def to_ri_cal_date_time_value
10
- RiCal::PropertyValue::DateTime.from_time(self)
9
+ def to_ri_cal_date_time_value(timezone_finder = nil) #:nodoc:
10
+ RiCal::PropertyValue::DateTime.new(
11
+ timezone_finder,
12
+ :value => strftime("%Y%m%dT%H%M%S"),
13
+ :params => {"TZID" => self.tzid || :default})
11
14
  end
12
15
 
13
- alias_method :to_ri_cal_date_or_date_time_value, :to_ri_cal_date_time_value
16
+ alias_method :to_ri_cal_date_or_date_time_value, :to_ri_cal_date_time_value #:nodoc:
17
+ alias_method :to_ri_cal_occurrence_list_value, :to_ri_cal_date_time_value #:nodoc:
14
18
 
15
19
  # Return the natural ri_cal_property for this object
16
- def to_ri_cal_property_value
17
- to_ri_cal_date_time_value
20
+ def to_ri_cal_property_value(timezone_finder = nil) #:nodoc:
21
+ to_ri_cal_date_time_value(timezone_finder)
18
22
  end
19
23
 
20
- # Return a proxy to this object which will be interpreted as a floating time.
24
+ # Return a copy of this object which will be interpreted as a floating time.
21
25
  def with_floating_timezone
22
- RiCal::TimeWithFloatingTimezone.new(self)
26
+ dup.set_tzid(:floating)
23
27
  end
24
28
  end
25
29
  end
@@ -0,0 +1,37 @@
1
+ module RiCal
2
+ module CoreExtensions #:nodoc:
3
+ module Time #:nodoc:
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ # Provides a tzid attribute for ::Time and ::DateTime
8
+ module TzidAccess
9
+ # The tzid attribute is used by RiCal, it should be a valid timezone identifier within a calendar,
10
+ # :floating to indicate a floating time, or nil to use the default timezone in effect
11
+ #
12
+ # See PropertyValue::DateTime#default_tzid= and Component::Calendar#tzid=
13
+ attr_accessor :tzid
14
+
15
+ # Convenience method, sets the tzid and returns the receiver
16
+ def set_tzid(time_zone_identifier)
17
+ self.tzid = time_zone_identifier
18
+ self
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ module TimeWithZoneExtension #:nodoc:
25
+ def tzid
26
+ time_zone.tzid.identifier
27
+ end
28
+ end
29
+ end
30
+
31
+ if Object.const_defined?(:ActiveSupport)
32
+ as = Object.const_get(:ActiveSupport)
33
+ if as.const_defined?(:TimeWithZone)
34
+ twz = as.const_get(:TimeWithZone)
35
+ twz.class_eval {include RiCal::TimeWithZoneExtension}
36
+ end
37
+ end
@@ -1,4 +1,5 @@
1
1
  require "#{File.dirname(__FILE__)}/time/conversions.rb"
2
+ require "#{File.dirname(__FILE__)}/time/tzid_access.rb"
2
3
  require "#{File.dirname(__FILE__)}/time/week_day_predicates.rb"
3
4
  require "#{File.dirname(__FILE__)}/time/calculations.rb"
4
5
  #- ©2009 Rick DeNatale
@@ -7,5 +8,6 @@ require "#{File.dirname(__FILE__)}/time/calculations.rb"
7
8
  class Time #:nodoc:
8
9
  include RiCal::CoreExtensions::Time::WeekDayPredicates
9
10
  include RiCal::CoreExtensions::Time::Calculations
10
- include RiCal::CoreExtensions::DateTime::Conversions
11
+ include RiCal::CoreExtensions::Time::Conversions
12
+ include RiCal::CoreExtensions::Time::TzidAccess
11
13
  end
@@ -0,0 +1,32 @@
1
+ module RiCal
2
+ #- ©2009 Rick DeNatale
3
+ #- All rights reserved. Refer to the file README.txt for the license
4
+ #
5
+ # FloatingTimezone represents the 'time zone' for a time or date time with no timezone
6
+ # Times with floating timezones are always interpreted in the timezone of the observer
7
+ class FloatingTimezone
8
+
9
+ def self.identifier #:nodoc:
10
+ nil
11
+ end
12
+
13
+ def self.tzinfo_timezone #:nodoc:
14
+ nil
15
+ end
16
+
17
+ def self.rational_utc_offset(local) #:nodoc:
18
+ Rational(0, 24)
19
+ end
20
+
21
+ # Return the time unchanged
22
+ def self.utc_to_local(time)
23
+ time.with_floating_timezone.to_ri_cal_date_time_value
24
+ end
25
+
26
+ # Return the time unchanged
27
+ def self.local_to_utc(time)
28
+ time.with_floating_timezone.to_ri_cal_date_time_value
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,8 @@
1
+ module RiCal
2
+ #- ©2009 Rick DeNatale
3
+ #- All rights reserved. Refer to the file README.txt for the license
4
+ #
5
+ # An InvalidPropertyValue error is raised when an improper value is assigned to a property
6
+ class InvalidPropertyValue < StandardError
7
+ end
8
+ end
@@ -9,11 +9,11 @@ module RiCal
9
9
  # such as importing a calendar which has forward reference to VTIMEZONE components.
10
10
  class InvalidTimezoneIdentifier < StandardError
11
11
 
12
- def self.not_found_in_calendar(identifier)
12
+ def self.not_found_in_calendar(identifier) #:nodoc:
13
13
  new("#{identifier.inspect} is not the identifier of a VTIMEZONE component of this calendar")
14
14
  end
15
15
 
16
- def self.invalid_tzinfo_identifier(identifier)
16
+ def self.invalid_tzinfo_identifier(identifier) #:nodoc:
17
17
  new("#{identifier.inspect} is not known to the tzinfo database")
18
18
  end
19
19
  end
@@ -84,8 +84,10 @@ module RiCal
84
84
  exclusion && occurrence[:start] == occurrence[:start]
85
85
  end
86
86
 
87
+ # Also exclude occurrences before the :starting date_time
87
88
  def exclude?(occurrence)
88
- exclusion_match?(occurrence, exclusion_for(occurrence))
89
+ exclusion_match?(occurrence, exclusion_for(occurrence)) ||
90
+ (@start && occurrence[:start].to_datetime < @start)
89
91
  end
90
92
 
91
93
  # yield each occurrence to a block
@@ -95,12 +97,12 @@ module RiCal
95
97
  yielded = 0
96
98
  @next_exclusion = @exrules.next_occurrence
97
99
  while (occurrence)
98
- if (@cutoff && occurrence[:start] >= @cutoff) || (@count && yielded >= @count)
100
+ if (@cutoff && occurrence[:start].to_datetime >= @cutoff) || (@count && yielded >= @count)
99
101
  occurrence = nil
100
102
  else
101
103
  unless exclude?(occurrence)
102
104
  yielded += 1
103
- yield @component.recurrence(occurrence)
105
+ yield @component.recurrence(occurrence)
104
106
  end
105
107
  occurrence = @rrules.next_occurrence
106
108
  end
data/lib/ri_cal/parser.rb CHANGED
@@ -19,7 +19,7 @@ module RiCal
19
19
  end
20
20
  end
21
21
 
22
- def parse_params(string) #:nodoc:
22
+ def self.parse_params(string) #:nodoc:
23
23
  if string
24
24
  string.split(";").inject({}) { |result, val|
25
25
  m = /^(.+)=(.+)$/.match(val)
@@ -32,11 +32,11 @@ module RiCal
32
32
  end
33
33
  end
34
34
 
35
- def params_and_value(string) #:nodoc:
35
+ def self.params_and_value(string, optional_initial_semi = false) #:nodoc:
36
36
  string = string.sub(/^:/,'')
37
- return ["", string] unless string.match(/^;/)
37
+ return [{}, string] unless optional_initial_semi || string.match(/^;/)
38
38
  segments = string.sub(';','').split(":")
39
- return ["", string] if segments.length < 2
39
+ return [{}, string] if segments.length < 2
40
40
  quote_count = 0
41
41
  gathering_params = true
42
42
  params = []
@@ -50,16 +50,16 @@ module RiCal
50
50
  values << segment
51
51
  end
52
52
  end
53
- [params.join(":"), values.join(":")]
53
+ [parse_params(params.join(":")), values.join(":")]
54
54
  end
55
-
55
+
56
56
  def separate_line(string) #:nodoc:
57
57
  match = string.match(/^([^;:]*)(.*)$/)
58
58
  name = match[1]
59
- params, value = *params_and_value(match[2])
59
+ params, value = *Parser.params_and_value(match[2])
60
60
  {
61
61
  :name => name,
62
- :params => parse_params(params),
62
+ :params => params,
63
63
  :value => value
64
64
  }
65
65
  end
@@ -224,7 +224,7 @@ module RiCal
224
224
 
225
225
  # set the value of the ATTENDEE property to multiple values
226
226
  # one or more instances of CalAddress may be passed to this method
227
- def attendees=(*ruby_values)
227
+ def attendees=(ruby_values)
228
228
  @attendee_property = ruby_values.map {|val| RiCal::PropertyValue::CalAddress.convert(self, val)}
229
229
  end
230
230
 
@@ -237,7 +237,7 @@ module RiCal
237
237
  # add one or more values to the ATTENDEE property
238
238
  # one or more instances of CalAddress may be passed to this method
239
239
  def add_attendees(*ruby_values)
240
- ruby_values.do {|val| self.attendee_property << RiCal::PropertyValue::CalAddress.convert(self, val)}
240
+ ruby_values.each {|val| self.attendee_property << RiCal::PropertyValue::CalAddress.convert(self, val)}
241
241
  end
242
242
 
243
243
  # add one value to the ATTENDEE property
@@ -249,7 +249,7 @@ module RiCal
249
249
  # remove one or more values from the ATTENDEE property
250
250
  # one or more instances of CalAddress may be passed to this method
251
251
  def remove_attendees(*ruby_values)
252
- ruby_values.do {|val| self.attendee_property.delete(RiCal::PropertyValue::CalAddress.convert(self, val))}
252
+ ruby_values.each {|val| self.attendee_property.delete(RiCal::PropertyValue::CalAddress.convert(self, val))}
253
253
  end
254
254
 
255
255
  # remove one value from the ATTENDEE property
@@ -261,7 +261,7 @@ module RiCal
261
261
  # return the value of the ATTENDEE property
262
262
  # which will be an array of instances of CalAddress
263
263
  def attendee
264
- attendee_property.map {|prop| prop ? prop.value : prop}
264
+ attendee_property.map {|prop| prop ? prop.ruby_value : prop}
265
265
  end
266
266
 
267
267
  def attendee_property_from_string(line) # :nodoc:
@@ -287,7 +287,7 @@ module RiCal
287
287
 
288
288
  # set the value of the ATTACH property to multiple values
289
289
  # one or more instances of Uri may be passed to this method
290
- def attachments=(*ruby_values)
290
+ def attachments=(ruby_values)
291
291
  @attach_property = ruby_values.map {|val| RiCal::PropertyValue::Uri.convert(self, val)}
292
292
  end
293
293
 
@@ -300,7 +300,7 @@ module RiCal
300
300
  # add one or more values to the ATTACH property
301
301
  # one or more instances of Uri may be passed to this method
302
302
  def add_attachments(*ruby_values)
303
- ruby_values.do {|val| self.attach_property << RiCal::PropertyValue::Uri.convert(self, val)}
303
+ ruby_values.each {|val| self.attach_property << RiCal::PropertyValue::Uri.convert(self, val)}
304
304
  end
305
305
 
306
306
  # add one value to the ATTACH property
@@ -312,7 +312,7 @@ module RiCal
312
312
  # remove one or more values from the ATTACH property
313
313
  # one or more instances of Uri may be passed to this method
314
314
  def remove_attachments(*ruby_values)
315
- ruby_values.do {|val| self.attach_property.delete(RiCal::PropertyValue::Uri.convert(self, val))}
315
+ ruby_values.each {|val| self.attach_property.delete(RiCal::PropertyValue::Uri.convert(self, val))}
316
316
  end
317
317
 
318
318
  # remove one value from the ATTACH property
@@ -324,7 +324,7 @@ module RiCal
324
324
  # return the value of the ATTACH property
325
325
  # which will be an array of instances of Uri
326
326
  def attach
327
- attach_property.map {|prop| prop ? prop.value : prop}
327
+ attach_property.map {|prop| prop ? prop.ruby_value : prop}
328
328
  end
329
329
 
330
330
  def attach_property_from_string(line) # :nodoc: