demingfactor-ri_cal 0.9.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 (167) hide show
  1. checksums.yaml +7 -0
  2. data/History.txt +402 -0
  3. data/Manifest.txt +161 -0
  4. data/README.txt +410 -0
  5. data/Rakefile +69 -0
  6. data/VERSION +1 -0
  7. data/bin/ri_cal +8 -0
  8. data/component_attributes/alarm.yml +10 -0
  9. data/component_attributes/calendar.yml +4 -0
  10. data/component_attributes/component_property_defs.yml +180 -0
  11. data/component_attributes/event.yml +45 -0
  12. data/component_attributes/freebusy.yml +16 -0
  13. data/component_attributes/journal.yml +35 -0
  14. data/component_attributes/timezone.yml +3 -0
  15. data/component_attributes/timezone_period.yml +11 -0
  16. data/component_attributes/todo.yml +46 -0
  17. data/copyrights.txt +1 -0
  18. data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
  19. data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
  20. data/docs/incrementers.txt +7 -0
  21. data/docs/rfc2445.pdf +0 -0
  22. data/lib/ri_cal/component/alarm.rb +19 -0
  23. data/lib/ri_cal/component/calendar.rb +257 -0
  24. data/lib/ri_cal/component/event.rb +58 -0
  25. data/lib/ri_cal/component/freebusy.rb +16 -0
  26. data/lib/ri_cal/component/journal.rb +27 -0
  27. data/lib/ri_cal/component/non_standard.rb +33 -0
  28. data/lib/ri_cal/component/t_z_info_timezone.rb +153 -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 +76 -0
  32. data/lib/ri_cal/component/timezone.rb +197 -0
  33. data/lib/ri_cal/component/todo.rb +42 -0
  34. data/lib/ri_cal/component.rb +256 -0
  35. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  36. data/lib/ri_cal/core_extensions/array.rb +7 -0
  37. data/lib/ri_cal/core_extensions/date/conversions.rb +56 -0
  38. data/lib/ri_cal/core_extensions/date.rb +13 -0
  39. data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
  40. data/lib/ri_cal/core_extensions/date_time.rb +15 -0
  41. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  42. data/lib/ri_cal/core_extensions/object.rb +8 -0
  43. data/lib/ri_cal/core_extensions/string/conversions.rb +57 -0
  44. data/lib/ri_cal/core_extensions/string.rb +8 -0
  45. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  46. data/lib/ri_cal/core_extensions/time/conversions.rb +42 -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 +55 -0
  49. data/lib/ri_cal/core_extensions/time.rb +14 -0
  50. data/lib/ri_cal/core_extensions.rb +11 -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 +148 -0
  58. data/lib/ri_cal/properties/alarm.rb +390 -0
  59. data/lib/ri_cal/properties/calendar.rb +164 -0
  60. data/lib/ri_cal/properties/event.rb +1523 -0
  61. data/lib/ri_cal/properties/freebusy.rb +593 -0
  62. data/lib/ri_cal/properties/journal.rb +1237 -0
  63. data/lib/ri_cal/properties/timezone.rb +150 -0
  64. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  65. data/lib/ri_cal/properties/todo.rb +1559 -0
  66. data/lib/ri_cal/properties.rb +12 -0
  67. data/lib/ri_cal/property_value/array.rb +27 -0
  68. data/lib/ri_cal/property_value/cal_address.rb +11 -0
  69. data/lib/ri_cal/property_value/date.rb +184 -0
  70. data/lib/ri_cal/property_value/date_time/additive_methods.rb +44 -0
  71. data/lib/ri_cal/property_value/date_time/time_machine.rb +159 -0
  72. data/lib/ri_cal/property_value/date_time/timezone_support.rb +100 -0
  73. data/lib/ri_cal/property_value/date_time.rb +359 -0
  74. data/lib/ri_cal/property_value/duration.rb +110 -0
  75. data/lib/ri_cal/property_value/geo.rb +11 -0
  76. data/lib/ri_cal/property_value/integer.rb +12 -0
  77. data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
  78. data/lib/ri_cal/property_value/period.rb +86 -0
  79. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +100 -0
  80. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +79 -0
  81. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +148 -0
  82. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +53 -0
  83. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +31 -0
  84. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_day_incrementer.rb +86 -0
  85. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_hour_incrementer.rb +31 -0
  86. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_minute_incrementer.rb +32 -0
  87. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_month_incrementer.rb +52 -0
  88. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_monthday_incrementer.rb +31 -0
  89. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_numbered_day_incrementer.rb +38 -0
  90. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_second_incrementer.rb +32 -0
  91. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_weekno_incrementer.rb +69 -0
  92. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_yearday_incrementer.rb +31 -0
  93. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/daily_incrementer.rb +28 -0
  94. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/frequency_incrementer.rb +80 -0
  95. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/hourly_incrementer.rb +23 -0
  96. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/list_incrementer.rb +106 -0
  97. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/minutely_incrementer.rb +23 -0
  98. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/monthly_incrementer.rb +33 -0
  99. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/null_sub_cycle_incrementer.rb +43 -0
  100. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/secondly_incrementer.rb +28 -0
  101. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/weekly_incrementer.rb +37 -0
  102. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/yearly_incrementer.rb +57 -0
  103. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer.rb +135 -0
  104. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
  105. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +64 -0
  106. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
  107. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +53 -0
  108. data/lib/ri_cal/property_value/recurrence_rule/time_manipulation.rb +42 -0
  109. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
  110. data/lib/ri_cal/property_value/recurrence_rule.rb +154 -0
  111. data/lib/ri_cal/property_value/text.rb +44 -0
  112. data/lib/ri_cal/property_value/uri.rb +11 -0
  113. data/lib/ri_cal/property_value/utc_offset.rb +33 -0
  114. data/lib/ri_cal/property_value/zulu_date_time.rb +34 -0
  115. data/lib/ri_cal/property_value.rb +159 -0
  116. data/lib/ri_cal/required_timezones.rb +55 -0
  117. data/lib/ri_cal.rb +187 -0
  118. data/parked_specs/ri_cal/claudio_a_bug_spec.rb +100 -0
  119. data/performance/empty_propval/subject.rb +43 -0
  120. data/performance/paris_eastern/subject.rb +90 -0
  121. data/performance/penultimate_weekday/subject.rb +15 -0
  122. data/performance/psm_big_enum/ical.ics +3171 -0
  123. data/performance/psm_big_enum/subject.rb +16 -0
  124. data/performance/utah_cycling/subject.rb +55 -0
  125. data/ri_cal.gemspec +244 -0
  126. data/script/benchmark_subject +23 -0
  127. data/script/console +10 -0
  128. data/script/destroy +14 -0
  129. data/script/generate +14 -0
  130. data/script/profile_subject +29 -0
  131. data/script/txt2html +71 -0
  132. data/spec/ri_cal/bugreports_spec.rb +276 -0
  133. data/spec/ri_cal/component/alarm_spec.rb +12 -0
  134. data/spec/ri_cal/component/calendar_spec.rb +88 -0
  135. data/spec/ri_cal/component/event_spec.rb +735 -0
  136. data/spec/ri_cal/component/freebusy_spec.rb +12 -0
  137. data/spec/ri_cal/component/journal_spec.rb +37 -0
  138. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +60 -0
  139. data/spec/ri_cal/component/timezone_spec.rb +236 -0
  140. data/spec/ri_cal/component/todo_spec.rb +112 -0
  141. data/spec/ri_cal/component_spec.rb +224 -0
  142. data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
  143. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
  144. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
  145. data/spec/ri_cal/fast_date_time_spec.rb +77 -0
  146. data/spec/ri_cal/inf_loop_spec.rb +78 -0
  147. data/spec/ri_cal/occurrence_enumerator_spec.rb +611 -0
  148. data/spec/ri_cal/parser_spec.rb +337 -0
  149. data/spec/ri_cal/property_value/date_spec.rb +53 -0
  150. data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
  151. data/spec/ri_cal/property_value/duration_spec.rb +126 -0
  152. data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
  153. data/spec/ri_cal/property_value/period_spec.rb +63 -0
  154. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
  155. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
  156. data/spec/ri_cal/property_value/text_spec.rb +25 -0
  157. data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
  158. data/spec/ri_cal/property_value_spec.rb +125 -0
  159. data/spec/ri_cal/required_timezones_spec.rb +67 -0
  160. data/spec/ri_cal_spec.rb +53 -0
  161. data/spec/spec.opts +4 -0
  162. data/spec/spec_helper.rb +50 -0
  163. data/tasks/gem_loader/load_active_support.rb +3 -0
  164. data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
  165. data/tasks/ri_cal.rake +412 -0
  166. data/tasks/spec.rake +102 -0
  167. metadata +246 -0
@@ -0,0 +1,50 @@
1
+ require 'date'
2
+ module RiCal
3
+ module CoreExtensions #:nodoc:
4
+ module DateTime #:nodoc:
5
+ #- ©2009 Rick DeNatale
6
+ #- All rights reserved. Refer to the file README.txt for the license
7
+ #
8
+ module Conversions #:nodoc:
9
+ # Return an RiCal::PropertyValue::DateTime representing the receiver
10
+ def to_ri_cal_date_time_value(timezone_finder = nil) #:nodoc:
11
+ RiCal::PropertyValue::DateTime.new(
12
+ timezone_finder,
13
+ :value => strftime("%Y%m%dT%H%M%S"),
14
+ :params => {"TZID" => self.tzid || :default})
15
+ end
16
+
17
+ alias_method :to_ri_cal_date_or_date_time_value, :to_ri_cal_date_time_value #:nodoc:
18
+ alias_method :to_ri_cal_occurrence_list_value, :to_ri_cal_date_time_value #:nodoc:
19
+
20
+ # Return the natural ri_cal_property for this object
21
+ def to_ri_cal_property_value(timezone_finder = nil) #:nodoc:
22
+ to_ri_cal_date_time_value(timezone_finder)
23
+ end
24
+
25
+ def to_overlap_range_start
26
+ self
27
+ end
28
+ alias_method :to_overlap_range_end, :to_overlap_range_start
29
+
30
+ # Return a copy of this object which will be interpreted as a floating time.
31
+ def with_floating_timezone
32
+ dup.set_tzid(:floating)
33
+ end
34
+
35
+ unless DateTime.instance_methods.map {|selector| selector.to_sym}.include?(:to_date)
36
+ # Converts self to a Ruby Date object; time portion is discarded
37
+ def to_date
38
+ ::Date.new(year, month, day)
39
+ end
40
+ end
41
+ unless DateTime.instance_methods.map {|selector| selector.to_sym}.include?(:to_datetime)
42
+ # To be able to keep Times, Dates and DateTimes interchangeable on conversions
43
+ def to_datetime
44
+ self
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,15 @@
1
+ require "ri_cal/core_extensions/date_time/conversions.rb"
2
+ require "ri_cal/core_extensions/time/tzid_access.rb"
3
+ require "ri_cal/core_extensions/time/week_day_predicates.rb"
4
+ require "ri_cal/core_extensions/time/calculations.rb"
5
+ require 'date'
6
+
7
+ class DateTime #:nodoc:
8
+ #- ©2009 Rick DeNatale
9
+ #- All rights reserved. Refer to the file README.txt for the license
10
+ #
11
+ include RiCal::CoreExtensions::Time::WeekDayPredicates
12
+ include RiCal::CoreExtensions::Time::Calculations
13
+ include RiCal::CoreExtensions::Time::TzidAccess
14
+ include RiCal::CoreExtensions::DateTime::Conversions
15
+ end
@@ -0,0 +1,20 @@
1
+ module RiCal
2
+ module CoreExtensions #:nodoc:
3
+ module Object #:nodoc:
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ module Conversions #:nodoc:
8
+ # Used to format rfc2445 output for RiCal
9
+ def to_rfc2445_string
10
+ to_s
11
+ end
12
+
13
+ # Used by RiCal specs returns the receiver
14
+ def to_ri_cal_ruby_value
15
+ self
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ require "ri_cal/core_extensions/object/conversions.rb"
2
+
3
+ class Object #:nodoc:
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ include RiCal::CoreExtensions::Object::Conversions
8
+ end
@@ -0,0 +1,57 @@
1
+ module RiCal
2
+ module CoreExtensions #:nodoc:
3
+ module String #:nodoc:
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ module Conversions #:nodoc:
8
+ def to_ri_cal_text_property
9
+ PropertyValue::Text.new(nil, :value => self)
10
+ end
11
+
12
+ # Parse the receiver as an RiCal::PropertyValue::DateTime
13
+ def to_ri_cal_date_time_value(timezone_finder = nil)
14
+ params, value = *Parser.params_and_value(self, :no_leading_semicolon)
15
+ if PropertyValue::DateTime.valid_string?(value)
16
+ PropertyValue::DateTime.new(timezone_finder, :params => params, :value => value)
17
+ else
18
+ raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 date-time")
19
+ end
20
+ end
21
+
22
+
23
+ def to_ri_cal_date_or_date_time_value(timezone_finder = nil)
24
+ params, value = *Parser.params_and_value(self, :no_leading_semicolon)
25
+ if PropertyValue::DateTime.valid_string?(value) || PropertyValue::Date.valid_string?(value)
26
+ PropertyValue.date_or_date_time(timezone_finder, :params => params, :value => value)
27
+ else
28
+ raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 date or date-time")
29
+ end
30
+ end
31
+
32
+ # Parse the receiver as an RiCal::PropertyValue::DurationValue
33
+ def to_ri_cal_duration_value(timezone_finder = nil)
34
+ params, value = *Parser.params_and_value(self)
35
+ if PropertyValue::Duration.valid_string?(value)
36
+ PropertyValue::Duration.new(timezone_finder, :params => params, :value => value)
37
+ else
38
+ raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 duration")
39
+ end
40
+ end
41
+
42
+ def to_ri_cal_occurrence_list_value(timezone_finder = nil)
43
+ params, value = *Parser.params_and_value(self, :no_leading_semicolon)
44
+ if PropertyValue::DateTime.valid_string?(value)
45
+ PropertyValue::DateTime.new(timezone_finder, :params => params, :value => value)
46
+ elsif PropertyValue::Date.valid_string?(value)
47
+ PropertyValue::Date.new(timezone_finder, :params => params, :value => value)
48
+ elsif PropertyValue::Period.valid_string?(value)
49
+ PropertyValue::Period.new(timezone_finder, :params => params, :value => value)
50
+ else
51
+ raise "Invalid value for occurrence list #{self.inspect}"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,8 @@
1
+ require "ri_cal/core_extensions/string/conversions.rb"
2
+
3
+ class String #:nodoc:
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ include RiCal::CoreExtensions::String::Conversions
8
+ end
@@ -0,0 +1,153 @@
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
+ # Provide calculation methods for use by the RiCal gem
8
+ # This module is included by Time, Date, and DateTime
9
+ module Calculations
10
+ # A predicate method used to determine if the receiver is within a leap year
11
+ def leap_year?
12
+ year % 4 == 0 && (year % 400 == 0 || year % 100 != 0)
13
+ end
14
+
15
+ # Return the number of days in the month which includes the receiver
16
+ def days_in_month
17
+ raw = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][self.month]
18
+ self.month == 2 && leap_year? ? raw + 1 : raw
19
+ end
20
+
21
+ # Return the date on which the first iso week with a given starting week day occurs
22
+ # for a given iso year
23
+ #
24
+ #
25
+ # From RFC 2445 page 43:
26
+ # A week is defined as a seven day period, starting on the day of the week defined to be the
27
+ # week start (see WKST). Week number one of the calendar year is the first week which contains
28
+ # at least four (4) days in that calendar
29
+ # year.
30
+ #
31
+ # == parameters
32
+ # year:: the iso year
33
+ # wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
34
+ # the ruby convention where 0 represents Sunday.
35
+ def self.iso_week_one(year, wkst)
36
+ #
37
+ # Note that wkst uses the ruby definition, with Sunday = 0
38
+ #
39
+ # A good article about calculating ISO week number is at
40
+ # http://www.boyet.com/Articles/PublishedArticles/CalculatingtheISOweeknumb.html
41
+ #
42
+ # RFC 2445 generalizes the notion of ISO week by allowing the start of the week to vary.
43
+ # In order to adopt the algorithm in the referenced article, we must determine, for each
44
+ # wkst value, the day in January which must be contained in week 1 of the year.
45
+ #
46
+ # For a given wkst week 1 for a year is the first week which
47
+ # 1) Starts with a day with a wday of wkst
48
+ # 2) Contains a majority (4 or more) of days in that year
49
+ #
50
+ # If end of prior Dec, start of Jan Week 1 starts on For WKST =
51
+
52
+ # MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU
53
+ # 01 02 03 04 05 06 07 08 09 10 11 12 13 14 01-07 02-08 03-09 04-10 05-11 06-12 07-13
54
+ # 31 01 02 03 04 05 06 07 08 09 10 11 12 13 31-06 01-07 02-08 03-09 04-10 05-11 06-12
55
+ # 30 31 01 02 03 04 05 06 07 08 09 10 11 12 30-05 31-06 01-07 02-08 03-09 04-10 05-11
56
+ # 29 30 31 01 02 03 04 05 06 07 08 09 10 11 29-04 30-05 31-06 01-07 02-08 03-09 04-10
57
+ # 28 29 30 31 01 02 03 04 05 06 07 08 09 10 04-10 29-04 30-05 31-06 01-07 02-08 03-09
58
+ # 27 28 29 30 31 01 02 03 04 05 06 07 08 09 03-09 04-10 29-04 30-05 31-06 01-07 02-08
59
+ # 26 27 28 29 30 31 01 02 03 04 05 06 07 08 02-08 03-09 04-10 29-04 30-05 31-06 01-07
60
+ # 25 26 27 28 29 30 31 01 02 03 04 05 06 07 01-07 02-08 03-09 04-10 29-04 30-05 31-06
61
+ # Week 1 must contain 4 4 4 4 ? ? ?
62
+ #
63
+ # So for a wkst of FR, SA, or SU, there is no date which MUST be contained in the 1st week
64
+ # We'll have to brute force that
65
+ if (1..4).include?(wkst)
66
+ # return the date of the wkst day which is less than or equal to jan4th
67
+ jan4th = ::Date.new(year, 1, 4)
68
+ result = jan4th - (convert_wday(jan4th.wday) - convert_wday(wkst))
69
+ else
70
+ # return the date of the wkst day which is greater than or equal to Dec 31 of the prior year
71
+ dec29th = ::Date.new(year-1, 12, 29)
72
+ result = dec29th + convert_wday(wkst) - convert_wday(dec29th.wday)
73
+ end
74
+ result
75
+ end
76
+
77
+ # Convert the receivers wday to RFC 2445 format. Whereas the Ruby time/date classes use
78
+ # 0 to represent Sunday, RFC 2445 uses 7.
79
+ def self.convert_wday(wday)
80
+ wday == 0 ? 7 : wday
81
+ end
82
+
83
+ # Return an array containing the iso year and iso week number for the receiver.
84
+ # Note that the iso year may be the year before or after the calendar year containing the receiver.
85
+ # == parameter
86
+ # wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
87
+ # the ruby convention where 0 represents Sunday.
88
+ def iso_year_and_week_one_start(wkst)
89
+ iso_year = self.year
90
+ date = ::Date.new(self.year, self.month, self.mday)
91
+ if (date >= ::Date.new(iso_year, 12, 29))
92
+ week_one_start = Calculations.iso_week_one(iso_year + 1, wkst)
93
+ if date < week_one_start
94
+ week_one_start = Calculations.iso_week_one(iso_year, wkst)
95
+ else
96
+ iso_year += 1
97
+ end
98
+ else
99
+ week_one_start = Calculations.iso_week_one(iso_year, wkst)
100
+ if (date < week_one_start)
101
+ iso_year -= 1
102
+ week_one_start = Calculations.iso_week_one(iso_year, wkst)
103
+ end
104
+ end
105
+ [iso_year, week_one_start]
106
+ end
107
+
108
+ def iso_year_and_week_num(wkst) #:nodoc:
109
+ iso_year, week_one_start = *iso_year_and_week_one_start(wkst)
110
+ [iso_year, (::Date.new(self.year, self.month, self.mday) - week_one_start).to_i / 7 + 1]
111
+ end
112
+
113
+ # return the number of weeks in the the iso year containing the receiver
114
+ # == parameter
115
+ # wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
116
+ # the ruby convention where 0 represents Sunday.
117
+ def iso_weeks_in_year(wkst)
118
+ iso_year, week_one_start = *iso_year_and_week_one_start(wkst)
119
+ probe_date = week_one_start + (7*52)
120
+ if probe_date.iso_year(wkst) == iso_year
121
+ 53
122
+ else
123
+ 52
124
+ end
125
+ end
126
+
127
+ # return the iso week number of the receiver
128
+ # == parameter
129
+ # wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
130
+ # the ruby convention where 0 represents Sunday.
131
+ def iso_week_num(wkst)
132
+ iso_year_and_week_num(wkst)[1]
133
+ end
134
+
135
+ # return the iso year of the receiver
136
+ # == parameter
137
+ # wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
138
+ # the ruby convention where 0 represents Sunday.
139
+ def iso_year(wkst)
140
+ iso_year_and_week_num(wkst)[0]
141
+ end
142
+
143
+ # return the first day of the iso year of the receiver
144
+ # == parameter
145
+ # wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
146
+ # the ruby convention where 0 represents Sunday.
147
+ def iso_year_start(wkst)
148
+ iso_year_and_week_one_start(wkst)[1]
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,42 @@
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
+ module Conversions
8
+ # Return an RiCal::PropertyValue::DateTime representing the receiver
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})
14
+ end
15
+
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:
18
+
19
+ # Return the natural ri_cal_property for this object
20
+ def to_ri_cal_property_value(timezone_finder = nil) #:nodoc:
21
+ to_ri_cal_date_time_value(timezone_finder)
22
+ end
23
+
24
+ def to_overlap_range_start
25
+ to_datetime
26
+ end
27
+
28
+ alias_method :to_overlap_range_end, :to_overlap_range_start
29
+
30
+ # Return a copy of this object which will be interpreted as a floating time.
31
+ def with_floating_timezone
32
+ dup.set_tzid(:floating)
33
+ end
34
+
35
+ unless Time.instance_methods.map {|selector| selector.to_sym}.include?(:to_datetime)
36
+ require 'date'
37
+ ::Time.send(:public, :to_datetime)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,50 @@
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
+
21
+ # Predicate indicating whether or not the instance represents a floating time
22
+ def has_floating_timezone?
23
+ tzid == :floating
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+
30
+ module TimeWithZoneExtension #:nodoc:
31
+ def tzid
32
+ utc? ? "UTC" : time_zone.tzinfo.identifier
33
+ end
34
+
35
+ # Predicate indicating whether or not the instance represents a floating time
36
+ def has_floating_timezone?
37
+ false
38
+ end
39
+
40
+ def to_ri_cal_date_time_value(timezone_finder=nil)
41
+ ::RiCal::PropertyValue::DateTime.new(timezone_finder, :params => {"TZID" => tzid}, :value => strftime("%Y%m%dT%H%M%S"))
42
+ end
43
+ alias_method :to_ri_cal_date_or_date_time_value, :to_ri_cal_date_time_value
44
+ alias_method :to_ri_cal_occurrence_list_value, :to_ri_cal_date_time_value
45
+ end
46
+ end
47
+
48
+ if RiCal::TimeWithZone
49
+ RiCal::TimeWithZone.class_eval {include RiCal::TimeWithZoneExtension}
50
+ end
@@ -0,0 +1,55 @@
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
+ # Provide predicate and related methods for use by the RiCal gem
8
+ # This module is included by Time, Date, and DateTime
9
+ module WeekDayPredicates
10
+
11
+ # Determine the day which falls on a particular weekday of the same month as the receiver
12
+ #
13
+ # == Parameters
14
+ # n:: the ordinal number being requested
15
+ # which_wday:: the weekday using Ruby time conventions, i.e. 0 => Sunday, 1 => Monday, ...
16
+
17
+ # e.g. to obtain the 3nd Tuesday of the receivers month use
18
+ #
19
+ # time.nth_wday_in_month(2, 2)
20
+ def nth_wday_in_month(n, which_wday, for_time = self)
21
+ first_of_month = for_time.to_ri_cal_property_value.change(:day => 1)
22
+ first_in_month = first_of_month.advance(:days => (which_wday - first_of_month.wday))
23
+ first_in_month = first_in_month.advance(:days => 7) if first_in_month.month != first_of_month.month
24
+ if n > 0
25
+ first_in_month.advance(:days => (7*(n - 1)))
26
+ else
27
+ possible = first_in_month.advance(:days => 21)
28
+ possible = possible.advance(:days => 7) while possible.month == first_in_month.month
29
+ last_in_month = possible.advance(:days => - 7)
30
+ (last_in_month.advance(:days => - (7*(n.abs - 1))))
31
+ end
32
+ end
33
+
34
+ # A predicate to determine whether or not the receiver falls on a particular weekday of its month.
35
+ #
36
+ # == Parameters
37
+ # n:: the ordinal number being requested
38
+ # which_wday:: the weekday using Ruby time conventions, i.e. 0 => Sunday, 1 => Monday, ...
39
+ def nth_wday_in_month?(n, which_wday)
40
+ target = nth_wday_in_month(n, which_wday)
41
+ [self.year, self.month, self.day] == [target.year, target.month, target.day]
42
+ end
43
+
44
+ # Return a DateTime which is the beginning of the first day on or before the receiver
45
+ # with the specified wday
46
+ def start_of_week_with_wkst(wkst)
47
+ wkst ||= 1
48
+ date = ::Date.civil(self.year, self.month, self.day)
49
+ date -= 1 while date.wday != wkst
50
+ date
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,14 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved. Refer to the file README.txt for the license
3
+ #
4
+ require "ri_cal/core_extensions/time/conversions.rb"
5
+ require "ri_cal/core_extensions/time/tzid_access.rb"
6
+ require "ri_cal/core_extensions/time/week_day_predicates.rb"
7
+ require "ri_cal/core_extensions/time/calculations.rb"
8
+
9
+ class Time #:nodoc:
10
+ include RiCal::CoreExtensions::Time::WeekDayPredicates
11
+ include RiCal::CoreExtensions::Time::Calculations
12
+ include RiCal::CoreExtensions::Time::Conversions
13
+ include RiCal::CoreExtensions::Time::TzidAccess
14
+ end
@@ -0,0 +1,11 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved. Refer to the file README.txt for the license
3
+ #
4
+
5
+ require "ri_cal/core_extensions/array.rb"
6
+ require "ri_cal/core_extensions/date.rb"
7
+ require "ri_cal/core_extensions/date_time.rb"
8
+ require "ri_cal/core_extensions/object.rb"
9
+ require "ri_cal/core_extensions/string.rb"
10
+ require "ri_cal/core_extensions/time.rb"
11
+