ri_cal 0.5.0

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