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,60 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. properties event.rb])
2
+
3
+ module RiCal
4
+ class Component
5
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ # An Event (VEVENT) calendar component groups properties describing a scheduled event.
8
+ # Events may have multiple occurrences
9
+ #
10
+ # Events may also contain one or more ALARM subcomponents
11
+ #
12
+ # to see the property accessing methods for this class see the RiCal::Properties::Event module
13
+ # to see the methods for enumerating occurrences of recurring events see the RiCal::OccurrenceEnumerator module
14
+ class Event < Component
15
+ include OccurrenceEnumerator
16
+
17
+ include RiCal::Properties::Event
18
+
19
+ def subcomponent_class #:nodoc:
20
+ {:alarm => Alarm }
21
+ end
22
+
23
+ def self.entity_name #:nodoc:
24
+ "VEVENT"
25
+ end
26
+
27
+ # Return a date_time representing the time at which the event starts
28
+ def start_time
29
+ dtstart_property ? dtstart.to_datetime : nil
30
+ end
31
+
32
+ # Return a date_time representing the time at which the event starts
33
+ def finish_property
34
+ if dtend_property
35
+ dtend_property
36
+ elsif duration_property
37
+ (dtstart_property + duration_property)
38
+ else
39
+ dtstart_property
40
+ end
41
+ end
42
+
43
+ # Return a date_time representing the time at which the event starts
44
+ def finish_time
45
+ prop = finish_property
46
+ prop ? prop.to_finish_time : nil
47
+ end
48
+
49
+ def zulu_occurrence_range_start_time
50
+ dtstart_property ? dtstart_property.to_zulu_occurrence_range_start_time : nil
51
+ end
52
+
53
+ def zulu_occurrence_range_finish_time
54
+ prop = finish_property
55
+ prop ? prop.to_zulu_occurrence_range_finish_time : nil
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. properties freebusy.rb])
2
+
3
+ module RiCal
4
+ class Component
5
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ # A Freebusy (VFREEBUSY) calendar component groups properties describing either a request for free/busy time,
8
+ # a response to a request for free/busy time, or a published set of busy time.
9
+ # to see the property accessing methods for this class see the RiCal::Properties::Freebusy module
10
+ class Freebusy < Component
11
+ include RiCal::Properties::Freebusy
12
+
13
+ def self.entity_name #:nodoc:
14
+ "VFREEBUSY"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[.. properties journal.rb])
3
+
4
+ module RiCal
5
+ class Component
6
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
7
+ #
8
+ # A Journal (VJOURNAL) calendar component groups properties describing a journal entry.
9
+ # Journals may have multiple occurrences
10
+ # to see the property accessing methods for this class see the RiCal::Properties::Journal module
11
+ # to see the methods for enumerating occurrences of recurring journals see the RiCal::OccurrenceEnumerator module
12
+ class Journal < Component
13
+ include RiCal::Properties::Journal
14
+ include RiCal::OccurrenceEnumerator
15
+
16
+ def self.entity_name #:nodoc:
17
+ "VJOURNAL"
18
+ end
19
+
20
+ # Return a date_time representing the time at which the event starts
21
+ def start_time
22
+ dtstart.to_datetime
23
+ end
24
+
25
+ # Journals take up no calendar time, so the finish time is always the same as the start_time
26
+ alias_method :finish_time, :start_time
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,123 @@
1
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
2
+ #
3
+ # A wrapper class for a Timezone implemented by the TZInfo Gem
4
+ # (or by Rails)
5
+ class RiCal::Component::TZInfoTimezone < RiCal::Component::Timezone
6
+
7
+ class Period #:nodoc: all
8
+
9
+ def initialize(which, this_period, prev_period)
10
+ @which = which
11
+ @onset = this_period.local_start.strftime("%Y%m%dT%H%M%S")
12
+ @offset_from = format_rfc2445_offset(prev_period.utc_total_offset)
13
+ @offset_to = format_rfc2445_offset(this_period.utc_total_offset)
14
+ @abbreviation = this_period.abbreviation
15
+ @rdates = []
16
+ end
17
+
18
+ def add_period(this_period)
19
+ @rdates << this_period.local_start.strftime("%Y%m%dT%H%M%S")
20
+ end
21
+
22
+
23
+ def format_rfc2445_offset(seconds) #:nodoc:
24
+ abs_seconds = seconds.abs
25
+ h = (abs_seconds/3600).floor
26
+ m = (abs_seconds - (h * 3600))/60
27
+ h *= -1 if seconds < 0
28
+ sprintf("%+03d%02d", h, m)
29
+ end
30
+
31
+ def export_to(export_stream)
32
+ export_stream.puts "BEGIN:#{@which}"
33
+ export_stream.puts "DTSTART:#{@onset}"
34
+ export_stream.puts "RDATE:#{@rdates.join(",")}"
35
+ export_stream.puts "TZOFFSETFROM:#{@offset_from}"
36
+ export_stream.puts "TZOFFSETTO:#{@offset_to}"
37
+ export_stream.puts "TZNAME:#{@abbreviation}"
38
+ export_stream.puts "END:#{@which}"
39
+ end
40
+ end
41
+
42
+ class Periods #:nodoc: all
43
+
44
+ def initialize
45
+ @dst_period = @std_period = @previous_period = nil
46
+ end
47
+
48
+ def daylight_period(this_period, previous_period)
49
+ @daylight_period ||= Period.new("DAYLIGHT", this_period, previous_period)
50
+ end
51
+
52
+ def standard_period(this_period, previous_period)
53
+ @standard_period ||= Period.new("STANDARD", this_period, previous_period)
54
+ end
55
+
56
+ def log_period(period)
57
+ @periods ||= []
58
+ @periods << period unless @periods.include?(period)
59
+ end
60
+
61
+ def add_period(this_period)
62
+ if @previous_period
63
+ if this_period.dst?
64
+ period = daylight_period(this_period, @previous_period)
65
+ else
66
+ period = standard_period(this_period, @previous_period)
67
+ end
68
+ period.add_period(this_period)
69
+ log_period(period)
70
+ end
71
+ @previous_period = this_period
72
+ end
73
+
74
+ def export_to(export_stream)
75
+ @periods.each {|period| period.export_to(export_stream)}
76
+ end
77
+ end
78
+
79
+ attr_reader :tzinfo_timezone #:nodoc:
80
+
81
+ def initialize(tzinfo_timezone) #:nodoc:
82
+ @tzinfo_timezone = tzinfo_timezone
83
+ end
84
+
85
+ # convert time from this time zone to utc time
86
+ def local_to_utc(time)
87
+ @tzinfo_timezone.local_to_utc(time.to_ri_cal_ruby_value)
88
+ end
89
+
90
+ # convert time from utc time to this time zone
91
+ def utc_to_local(time)
92
+ @tzinfo_timezone.utc_to_local(time.to_ri_cal_ruby_value)
93
+ end
94
+
95
+ # return the time zone identifier
96
+ def identifier
97
+ @tzinfo_timezone.identifier
98
+ end
99
+
100
+ def export_local_to(export_stream, local_start, local_end) #:nodoc:
101
+ export_utc_to(export_stream, local_to_utc(local_start.to_ri_cal_ruby_value), local_to_utc(local_end.to_ri_cal_ruby_value))
102
+ end
103
+
104
+ def to_rfc2445_string(utc_start, utc_end) #:nodoc:
105
+ export_stream = StringIO.new
106
+ export_utc_to(export_stream, utc_start, utc_end)
107
+ export_stream.string
108
+ end
109
+
110
+ def export_utc_to(export_stream, utc_start, utc_end) #:nodoc:
111
+ export_stream.puts "BEGIN:VTIMEZONE","TZID;X-RICAL-TZSOURCE=TZINFO:#{identifier}"
112
+ periods = Periods.new
113
+ period = tzinfo_timezone.period_for_utc(utc_start)
114
+ #start with the period before the one containing utc_start
115
+ period = tzinfo_timezone.period_for_utc(period.utc_start - 1)
116
+ while period && period.utc_start < utc_end
117
+ periods.add_period(period)
118
+ period = tzinfo_timezone.period_for_utc(period.utc_end + 1)
119
+ end
120
+ periods.export_to(export_stream)
121
+ export_stream.puts "END:VTIMEZONE\n"
122
+ end
123
+ end
@@ -0,0 +1,196 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. properties timezone.rb])
2
+
3
+ module RiCal
4
+ class Component
5
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ # An Timezone (VTIMEZONE) calendar component describes a timezone used within the calendar.
8
+ # A Timezone has two or more TimezonePeriod subcomponents which describe the transitions between
9
+ # standard and daylight saving time.
10
+ #
11
+ # to see the property accessing methods for this class see the RiCal::Properties::Timezone module
12
+ class Timezone < Component
13
+ include RiCal::Properties::Timezone
14
+
15
+ # The identifier of the timezone, e.g. "Europe/Paris".
16
+ def identifier
17
+ tzid
18
+ end
19
+
20
+ # An alias for identifier.
21
+ def name
22
+ # Don't use alias, as identifier gets overridden.
23
+ identifier
24
+ end
25
+
26
+ def rational_utc_offset(local) #:nodoc:
27
+ Rational(period_for_local(local, true).utc_total_offset, 3600) / 24
28
+ end
29
+
30
+ # Returns the TimezonePeriod for the given UTC time. utc can either be a DateTime,
31
+ # Time or integer timestamp (Time.to_i). Any timezone information in utc is ignored (it is treated as a UTC time).
32
+ def period_for_utc(time)
33
+ last_period(last_before_utc(standard, time), last_before_utc(daylight, time))
34
+ end
35
+
36
+ # Returns the set of TimezonePeriod instances that are valid for the given
37
+ # local time as an array. If you just want a single period, use
38
+ # period_for_local instead and specify how ambiguities should be resolved.
39
+ # Returns an empty array if no periods are found for the given time.
40
+ def periods_for_local(local)
41
+ local = local.to_ri_cal_date_time_value
42
+ candidate_standard = last_before_local(standard, local)
43
+ candidate_daylight = last_before_local(daylight, local)
44
+ if candidate_daylight && candidate_daylight.swallows_local?(local, candidate_standard)
45
+ [] # Invalid local time
46
+ elsif candidate_standard
47
+ if candidate_daylight
48
+ if candidate_daylight.dtstart > candidate_standard.dtstart
49
+ [candidate_daylight]
50
+ elsif candidate_standard.ambiguous_local?(local)
51
+ [candidate_daylight, candidate_standard]
52
+ else
53
+ [candidate_standard].compact
54
+ end
55
+ else
56
+ [candidate_standard].compact
57
+ end
58
+ end
59
+ end
60
+
61
+
62
+ # Returns the TimezonePeriod for the given local time. local can either be
63
+ # a DateTime, Time or integer timestamp (Time.to_i). Any timezone
64
+ # information in local is ignored (it is treated as a time in the current
65
+ # timezone).
66
+ #
67
+ # Warning: There are local times that have no equivalent UTC times (e.g.
68
+ # in the transition from standard time to daylight savings time). There are
69
+ # also local times that have more than one UTC equivalent (e.g. in the
70
+ # transition from daylight savings time to standard time).
71
+ #
72
+ # In the first case (no equivalent UTC time), a PeriodNotFound exception
73
+ # will be raised.
74
+ #
75
+ # In the second case (more than one equivalent UTC time), an AmbiguousTime
76
+ # exception will be raised unless the optional dst parameter or block
77
+ # handles the ambiguity.
78
+ #
79
+ # If the ambiguity is due to a transition from daylight savings time to
80
+ # standard time, the dst parameter can be used to select whether the
81
+ # daylight savings time or local time is used. For example,
82
+ #
83
+ # Timezone.get('America/New_York').period_for_local(DateTime.new(2004,10,31,1,30,0))
84
+ #
85
+ # would raise an AmbiguousTime exception.
86
+ #
87
+ # Specifying dst=true would the daylight savings period from April to
88
+ # October 2004. Specifying dst=false would return the standard period
89
+ # from October 2004 to April 2005.
90
+ #
91
+ # If the dst parameter does not resolve the ambiguity, and a block is
92
+ # specified, it is called. The block must take a single parameter - an
93
+ # array of the periods that need to be resolved. The block can select and
94
+ # return a single period or return nil or an empty array
95
+ # to cause an AmbiguousTime exception to be raised.
96
+ #
97
+ # TODO: need to check for ambiguity
98
+ def period_for_local(local, dst=nil)
99
+ results = periods_for_local(local)
100
+
101
+ if results.empty?
102
+ raise TZInfo::PeriodNotFound
103
+ elsif results.size < 2
104
+ results.first
105
+ else
106
+ # ambiguous result try to resolve
107
+
108
+ unless dst.nil?
109
+ matches = results.find_all {|period| period.dst? == dst}
110
+ results = matches unless matches.empty?
111
+ end
112
+
113
+ if results.size < 2
114
+ results.first
115
+ else
116
+ # still ambiguous, try the block
117
+
118
+ if block_given?
119
+ results = yield results
120
+ end
121
+
122
+ if results.is_a?(TimezonePeriod)
123
+ results
124
+ elsif results && results.size == 1
125
+ results.first
126
+ else
127
+ raise TZInfo::AmbiguousTime, "#{local} is an ambiguous local time."
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ # convert time from utc time to this time zone
134
+ def utc_to_local(time)
135
+ time = time.to_ri_cal_date_time_value
136
+ converted = time + period_for_utc(time).tzoffsetto_property
137
+ converted.tzid = identifier
138
+ converted
139
+ end
140
+
141
+ # convert time from this time zone to utc time
142
+ def local_to_utc(time)
143
+ time = time.to_ri_cal_date_time_value
144
+ period = period_for_local(time)
145
+ converted = time - period.tzoffsetto_property
146
+ converted.tzid = "UTC"
147
+ converted
148
+ end
149
+ end
150
+
151
+ def self.entity_name #:nodoc:
152
+ "VTIMEZONE"
153
+ end
154
+
155
+ def standard #:nodoc:
156
+ @subcomponents["STANDARD"]
157
+ end
158
+
159
+ def daylight #:nodoc:
160
+ @subcomponents["DAYLIGHT"]
161
+ end
162
+
163
+ def last_period(standard, daylight) #:nodoc:
164
+ if standard
165
+ if daylight
166
+ standard.dtstart > daylight.dtstart ? standard : daylight
167
+ else
168
+ standard
169
+ end
170
+ else
171
+ daylight
172
+ end
173
+ end
174
+
175
+ def last_before_utc(period_array, time) #:nodoc:
176
+ candidates = period_array.map {|period|
177
+ period.last_before_utc(time)
178
+ }
179
+ result = candidates.max {|a, b| a.dtstart_property <=> b.dtstart_property}
180
+ result
181
+ end
182
+
183
+ def last_before_local(period_array, time) #:nodoc:
184
+ candidates = period_array.map {|period|
185
+ period.last_before_local(time)
186
+ }
187
+ result = candidates.max {|a, b| a.dtstart_property <=> b.dtstart_property}
188
+ result
189
+ end
190
+ end
191
+ end
192
+
193
+
194
+ %w[timezone_period.rb daylight_period.rb standard_period.rb].each do |filename|
195
+ require "#{File.dirname(__FILE__)}/timezone/#{filename}"
196
+ end
@@ -0,0 +1,25 @@
1
+ module RiCal
2
+ class Component
3
+ class Timezone
4
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ # A DaylightPeriod is a TimezonePeriod during which daylight saving time *is* in effect
7
+ class DaylightPeriod < TimezonePeriod #:nodoc: all
8
+
9
+ def self.entity_name #:nodoc:
10
+ "DAYLIGHT"
11
+ end
12
+
13
+ def dst?
14
+ true
15
+ end
16
+
17
+ def swallows_local?(local, std_candidate)
18
+ ([local.year, local.month, local.day] == [dtstart.year,dtstart.month, dtstart.day]) &&
19
+ local >= dtstart_property &&
20
+ local.advance(:seconds => (std_candidate.utc_total_offset - utc_total_offset)) < dtstart_property
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end