rubyredrick-ri_cal 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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: