rubyredrick-ri_cal 0.5.3 → 0.6.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.
data/History.txt CHANGED
@@ -1,3 +1,14 @@
1
+ === 0.6.0 - 5 June 2009
2
+ Time for a minor version bump.
3
+ * Improved overall enumeration performance bypassing most of the effects of the poor performance of Ruby's DateTime class.
4
+ * Added a framework for performance monitoring during development.
5
+ - New performance directory with subdirs for code to be monitored for performance (subjects)
6
+ - New script files:
7
+ script/benchmark_subject runs a ruby benchmark on one performance subject
8
+ script/profile_subject runs ruby-prof for a subject and puts a kcachegrind compatible calltree in the performance_data directory.
9
+ - New rake tasks:
10
+ performance:benchmark runs benchmarks against all subjects in the performance directory and produces a consolidated output file in performance_data/benchmarks.out
11
+ performance:profile runs script/profile_subject against all subjects in the performance directory.
1
12
  === 0.5.3 - 1 June, 2009
2
13
  * Improved performance of time zone enumeration, TimeZonePeriod now caches occurrences
3
14
  * Added a profiling directory which contains ruby programs which benchmark and/or profile performance
data/Manifest.txt CHANGED
@@ -46,6 +46,7 @@ lib/ri_cal/core_extensions/time/calculations.rb
46
46
  lib/ri_cal/core_extensions/time/conversions.rb
47
47
  lib/ri_cal/core_extensions/time/tzid_access.rb
48
48
  lib/ri_cal/core_extensions/time/week_day_predicates.rb
49
+ lib/ri_cal/fast_date_time.rb
49
50
  lib/ri_cal/floating_timezone.rb
50
51
  lib/ri_cal/invalid_property_value.rb
51
52
  lib/ri_cal/invalid_timezone_identifer.rb
@@ -89,15 +90,18 @@ lib/ri_cal/property_value/text.rb
89
90
  lib/ri_cal/property_value/uri.rb
90
91
  lib/ri_cal/property_value/utc_offset.rb
91
92
  lib/ri_cal/required_timezones.rb
92
- profiling/ical_files/profile3.ics
93
- profiling/profile1.rb
94
- profiling/profile2.rb
95
- profiling/profile3.rb
93
+ performance/paris_eastern/subject.rb
94
+ performance/penultimate_weekday/subject.rb
95
+ performance/psm_big_enum/ical.ics
96
+ performance/psm_big_enum/subject.rb
97
+ performance/utah_cycling/subject.rb
96
98
  ri_cal.gemspec
97
99
  sample_ical_files/from_ical_dot_app/test1.ics
100
+ script/benchmark_subject
98
101
  script/console
99
102
  script/destroy
100
103
  script/generate
104
+ script/profile_subject
101
105
  script/txt2html
102
106
  spec/ri_cal/component/alarm_spec.rb
103
107
  spec/ri_cal/component/calendar_spec.rb
@@ -111,6 +115,7 @@ spec/ri_cal/component_spec.rb
111
115
  spec/ri_cal/core_extensions/string/conversions_spec.rb
112
116
  spec/ri_cal/core_extensions/time/calculations_spec.rb
113
117
  spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb
118
+ spec/ri_cal/fast_date_time_spec.rb
114
119
  spec/ri_cal/occurrence_enumerator_spec.rb
115
120
  spec/ri_cal/parser_spec.rb
116
121
  spec/ri_cal/property_value/date_spec.rb
data/README.txt CHANGED
@@ -348,12 +348,9 @@ or by a recent(>= 2.2) version of the ActiveSupport gem which is part of Ruby on
348
348
 
349
349
  === From github
350
350
 
351
- #TODO: publish to github
352
-
353
351
  ==== As a Gem
354
352
 
355
- #TODO: add the gem source info for github
356
- sudo gem install ????? --source http://github.com/????
353
+ sudo gem install rubyredrick-ri_cal --source http://gems.github.com/
357
354
 
358
355
  ==== From source
359
356
 
@@ -140,7 +140,6 @@ module RiCal
140
140
 
141
141
 
142
142
  def rational_utc_offset(local)
143
- # 86400 is the number of seconds in a day
144
143
  RiCal.RationalOffset[tzinfo.period_for_local(local, true).utc_total_offset]
145
144
  end
146
145
 
@@ -47,17 +47,7 @@ module RiCal
47
47
  raise "Invalid value for occurrence list #{self.inspect}"
48
48
  end
49
49
  end
50
-
51
- # code stolen from ActiveSupport Gem
52
- unless ::String.instance_methods.include?("camelize")
53
- # Convert the receiver to camelized form
54
- # This method duplicates the method provided by ActiveSupport, and will only be defined
55
- # by the RiCal gem if it is not already defined.
56
- def camelize
57
- self.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
58
- end
59
- end
60
- end
50
+ end
61
51
  end
62
52
  end
63
53
  end
@@ -27,23 +27,6 @@ module RiCal
27
27
  end
28
28
 
29
29
  unless defined? ActiveSupport
30
- # Converts a Time object to a Date, dropping hour, minute, and second precision.
31
- #
32
- # my_time = Time.now # => Mon Nov 12 22:59:51 -0500 2007
33
- # my_time.to_date # => Mon, 12 Nov 2007
34
- #
35
- # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009
36
- # your_time.to_date # => Tue, 13 Jan 2009
37
- def to_date
38
- ::Date.new(year, month, day)
39
- end
40
-
41
- # A method to keep Time, Date and DateTime instances interchangeable on conversions.
42
- # In this case, it simply returns +self+.
43
- def to_time
44
- self
45
- end
46
-
47
30
  # Converts a Time instance to a Ruby DateTime instance, preserving UTC offset.
48
31
  #
49
32
  # my_time = Time.now # => Mon Nov 12 23:04:21 -0500 2007
@@ -8,39 +8,6 @@ module RiCal
8
8
  # This module is included by Time, Date, and DateTime
9
9
  module WeekDayPredicates
10
10
 
11
- # Determine the equivalent time on the day which falls on a particular weekday of the same year 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 2nd Monday of the receivers year use
18
- #
19
- # time.nth_wday_in_year(2, 1)
20
- def nth_wday_in_year(n, which_wday, for_time = self)
21
- if n > 0
22
- first_of_year = for_time.to_ri_cal_property_value.change(:month => 1, :day => 1)
23
- first_in_year = first_of_year.advance(:days => (which_wday - first_of_year.wday + 7) % 7)
24
- first_in_year.advance(:days => (7*(n - 1)))
25
- else
26
- december25 = for_time.to_ri_cal_property_value.change(:month => 12, :day => 25)
27
- last_in_year = december25.advance(:days => (which_wday - december25.wday + 7) % 7)
28
- last_in_year.advance(:days => (7 * (n + 1)))
29
- end
30
- end
31
-
32
- # A predicate to determine whether or not the receiver falls on a particular weekday of its year.
33
- #
34
- # See #nth_wday_in_year
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_year?(n, which_wday)
40
- target = nth_wday_in_year(n, which_wday)
41
- [self.year, self.mon, self.day] == [target.year, target.mon, target.day]
42
- end
43
-
44
11
  # Determine the day which falls on a particular weekday of the same month as the receiver
45
12
  #
46
13
  # == Parameters
@@ -0,0 +1,214 @@
1
+ module RiCal
2
+ #- ©2009 Rick DeNatale
3
+ #- All rights reserved. Refer to the file README.txt for the license
4
+ #
5
+ # FastDateTime mimics the Ruby Standard library DateTime class but avoids the use of Rational
6
+ # Instead of using a Rational for the utc offset, FastDateTime uses an integer seconds value
7
+ class FastDateTime
8
+ attr_accessor :date, :hour, :min, :sec, :offset, :secs_since_bod
9
+
10
+ SECONDS_IN_A_DAY = 60*60*24 unless defined? SECONDS_IN_A_DAY
11
+
12
+ include Comparable
13
+
14
+ def initialize(year, month, day, hour, min, sec, offset_seconds)
15
+ @date = Date.civil(year, month, day)
16
+ @secs_since_bod = hms_to_seconds(hour, min, sec)
17
+ @hour, @min, @sec, @offset = hour, min, sec, offset_seconds
18
+ end
19
+
20
+ def self.from_date_time(date_time)
21
+ new(date_time.year, date_time.month, date_time.day, date_time.hour, date_time.min, date_time.sec, (date_time.offset * SECONDS_IN_A_DAY).to_i)
22
+ end
23
+
24
+ alias_method :utc_offset_seconds, :offset
25
+
26
+ def ical_str
27
+ "%04d%02d%02dT%02d%02d%02d" % [year, month, day, hour, min, sec]
28
+ end
29
+
30
+ def ical_date_str
31
+ "%04d%02d%02d" % [year, month, day]
32
+ end
33
+
34
+ def year
35
+ @date.year
36
+ end
37
+
38
+ def month
39
+ @date.month
40
+ end
41
+
42
+ alias_method :mon, :month
43
+
44
+ def day
45
+ @date.day
46
+ end
47
+
48
+ def wday
49
+ @date.wday
50
+ end
51
+
52
+ def to_datetime
53
+ DateTime.civil(year, month, day, hour, min, sec, RiCal.RationalOffset[utc_offset_seconds])
54
+ end
55
+
56
+ def ==(other)
57
+ [date, secs_since_bod, offset] == [other.date, other.secs_since_bod, other.offset]
58
+ end
59
+
60
+ def <=> (other)
61
+ if FastDateTime === other
62
+ [date, secs_since_bod] <=> [other.date, other.secs_since_bod]
63
+ else
64
+ [year, month, day, hour, min, sec] <=> [other.year, other.month, other.day, other.hour, other.min, other.sec]
65
+ end
66
+ end
67
+
68
+ def to_s
69
+ "#{year}/#{month}/#{day} #{hour}:#{min}:#{sec} #{offset}"
70
+ end
71
+
72
+ # def jd
73
+ # date.jd
74
+ # end
75
+ #
76
+ def days_in_month
77
+ date.days_in_month
78
+ end
79
+
80
+ alias_method :inspect, :to_s
81
+
82
+ # Return a new FastDateTime based on the receiver but with changes specified by the options
83
+ def change(options)
84
+ FastDateTime.new(
85
+ options[:year] || year,
86
+ options[:month] || month,
87
+ options[:day] || day,
88
+ options[:hour] || hour,
89
+ options[:min] || (options[:hour] ? 0 : min),
90
+ options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec),
91
+ options[:offset] || offset
92
+ )
93
+ end
94
+
95
+ # def new_offset(ofst)
96
+ # if ofst == offset
97
+ # self
98
+ # else
99
+ # advance(:seconds => offset - ofset, :offset => ofst)
100
+ # end
101
+ # end
102
+
103
+ def hms_to_seconds(hours, minutes, seconds)
104
+ seconds + 60 *(minutes + (60 * hours))
105
+ end
106
+
107
+ def seconds_to_hms(total_seconds)
108
+ sign = total_seconds <=> 0
109
+ remaining = total_seconds.abs
110
+ seconds = sign * (remaining % 60)
111
+ remaining = remaining / 60
112
+ minutes = sign * (remaining % 60)
113
+ [remaining / 60, minutes, seconds]
114
+ end
115
+
116
+ def adjust_day_delta(day_delta, new_secs_since_bod)
117
+ if new_secs_since_bod == 0
118
+ [day_delta, new_secs_since_bod]
119
+ elsif new_secs_since_bod > 0
120
+ [day_delta + (new_secs_since_bod / SECONDS_IN_A_DAY), new_secs_since_bod % SECONDS_IN_A_DAY]
121
+ else new_secs_since_bod
122
+ [day_delta - (1 + new_secs_since_bod.abs / SECONDS_IN_A_DAY),
123
+ SECONDS_IN_A_DAY - (new_secs_since_bod.abs % SECONDS_IN_A_DAY)]
124
+ end
125
+ end
126
+
127
+
128
+ def advance(options) # :nodoc:
129
+ new_date = @date
130
+ new_offset = options[:offset] || offset
131
+ month_delta = (options[:years] || 0) * 12 + (options[:months] || 0)
132
+ day_delta = (options[:weeks] || 0) * 7 + (options[:days] || 0)
133
+ sec_delta = hms_to_seconds((options[:hours] || 0), (options[:minutes] || 0), (options[:seconds] || 0))
134
+ day_delta, new_secs_since_bod = *adjust_day_delta(day_delta, secs_since_bod + sec_delta)
135
+ new_hour, new_min, new_sec = *seconds_to_hms(new_secs_since_bod)
136
+ new_date = new_date >> month_delta unless month_delta == 0
137
+ new_date += day_delta unless day_delta == 0
138
+ FastDateTime.new(new_date.year, new_date.month, new_date.day, new_hour, new_min, new_sec, new_offset)
139
+ end
140
+
141
+ # Determine the day which falls on a particular weekday of the same month as the receiver
142
+ #
143
+ # == Parameters
144
+ # n:: the ordinal number being requested
145
+ # which_wday:: the weekday using Ruby time conventions, i.e. 0 => Sunday, 1 => Monday, ...
146
+
147
+ # e.g. to obtain the 3nd Tuesday of the receivers month use
148
+ #
149
+ # time.nth_wday_in_month(2, 2)
150
+ def nth_wday_in_month(n, which_wday)
151
+ first_of_month = change(:day => 1)
152
+ first_in_month = first_of_month.advance(:days => (which_wday - first_of_month.wday))
153
+ first_in_month = first_in_month.advance(:days => 7) if first_in_month.month != first_of_month.month
154
+ if n > 0
155
+ first_in_month.advance(:days => (7*(n - 1)))
156
+ else
157
+ possible = first_in_month.advance(:days => 21)
158
+ possible = possible.advance(:days => 7) while possible.month == first_in_month.month
159
+ last_in_month = possible.advance(:days => - 7)
160
+ (last_in_month.advance(:days => - (7*(n.abs - 1))))
161
+ end
162
+ end
163
+
164
+ # Determine the equivalent time on the day which falls on a particular weekday of the same year as the receiver
165
+ #
166
+ # == Parameters
167
+ # n:: the ordinal number being requested
168
+ # which_wday:: the weekday using Ruby time conventions, i.e. 0 => Sunday, 1 => Monday, ...
169
+
170
+ # e.g. to obtain the 2nd Monday of the receivers year use
171
+ #
172
+ # time.nth_wday_in_year(2, 1)
173
+ def nth_wday_in_year(n, which_wday)
174
+ if n > 0
175
+ first_of_year = change(:month => 1, :day => 1)
176
+ first_in_year = first_of_year.advance(:days => (which_wday - first_of_year.wday + 7) % 7)
177
+ first_in_year.advance(:days => (7*(n - 1)))
178
+ else
179
+ december25 = change(:month => 12, :day => 25)
180
+ last_in_year = december25.advance(:days => (which_wday - december25.wday + 7) % 7)
181
+ last_in_year.advance(:days => (7 * (n + 1)))
182
+ end
183
+ end
184
+
185
+
186
+ # Return a DateTime which is the beginning of the first day on or before the receiver
187
+ # with the specified wday
188
+ def start_of_week_with_wkst(wkst)
189
+ wkst ||= 1
190
+ date = @date
191
+ date -= 1 while date.wday != wkst
192
+ date
193
+ end
194
+
195
+ def iso_weeks_in_year(wkst)
196
+ @date.iso_weeks_in_year(wkst)
197
+ end
198
+
199
+ def iso_year_start(wkst)
200
+ @date.iso_year_start(wkst)
201
+ end
202
+
203
+ def iso_year_and_week_one_start(wkst)
204
+ @date.iso_year_and_week_one_start(wkst)
205
+ end
206
+
207
+ def cmp_fast_date_time_value(other)
208
+ other <=> self
209
+ end
210
+
211
+
212
+ end
213
+
214
+ end
@@ -222,10 +222,10 @@ module RiCal
222
222
  @exdate_property = nil
223
223
  @recurrence_id_property = occurrence_start
224
224
  if @dtend_property && !occurrence_end
225
- occurrence_end = occurrence_start + (@dtend_property - @dtstart_property)
225
+ occurrence_end = occurrence_start + (@dtend_property - @dtstart_property)
226
226
  end
227
- @dtstart_property = dtstart_property.for_occurrence(occurrence_start)
228
- @dtend_property = dtend_property.for_occurrence(occurrence_end) if @dtend_property
227
+ @dtstart_property = @dtstart_property.for_occurrence(occurrence_start)
228
+ @dtend_property = (@dtend_property || @dtstart_property).for_occurrence(occurrence_end) if occurrence_end
229
229
  self
230
230
  end
231
231
 
@@ -15,7 +15,7 @@ module RiCal
15
15
  # Returns the value of the reciever as an RFC 2445 iCalendar string
16
16
  def value
17
17
  if @date_time_value
18
- @date_time_value.strftime("%Y%m%d")
18
+ @date_time_value.ical_date_str
19
19
  else
20
20
  nil
21
21
  end
@@ -34,9 +34,11 @@ module RiCal
34
34
  when nil
35
35
  @date_time_value = nil
36
36
  when String
37
- @date_time_value = ::DateTime.parse(::DateTime.parse(val).strftime("%Y%m%d"))
37
+ @date_time_value = FastDateTime.from_date_time(::DateTime.parse(::DateTime.parse(val).strftime("%Y%m%d")))
38
38
  when ::Time, ::Date, ::DateTime
39
- @date_time_value = ::DateTime.parse(val.strftime("%Y%m%d"))
39
+ @date_time_value = FastDateTime.from_date_time(::DateTime.parse(val.strftime("%Y%m%d")))
40
+ when FastDateTime
41
+ @date_time_value = val
40
42
  end
41
43
  end
42
44
 
@@ -69,7 +71,7 @@ module RiCal
69
71
 
70
72
  # Returns the ruby representation a ::Date
71
73
  def ruby_value
72
- ::Date.parse(@date_time_value.strftime("%Y%m%d"))
74
+ @date_time_value.date
73
75
  end
74
76
 
75
77
  alias_method :to_ri_cal_ruby_value, :ruby_value
@@ -89,24 +91,12 @@ module RiCal
89
91
  self
90
92
  end
91
93
 
92
- def compute_change(d, options) #:nodoc:
93
- ::Date.civil((options[:year] || d.year), (options[:month] || d.month), (options[:day] || d.day))
94
- end
95
-
96
- def compute_advance(d, options) #:nodoc:
97
- d = d >> options[:years] * 12 if options[:years]
98
- d = d >> options[:months] if options[:months]
99
- d = d + options[:weeks] * 7 if options[:weeks]
100
- d = d + options[:days] if options[:days]
101
- compute_change(@date_time_value, :year => d.year, :month => d.month, :day => d.day)
102
- end
103
-
104
94
  def advance(options) #:nodoc:
105
- PropertyValue::Date.new(timezone_finder, :value => compute_advance(@date_time_value, options), :params =>(params ? params.dup : nil) )
95
+ PropertyValue::Date.new(timezone_finder, :value => @date_time_value.advance(options), :params =>(params ? params.dup : nil) )
106
96
  end
107
97
 
108
98
  def change(options) #:nodoc:
109
- PropertyValue::Date.new(timezone_finder,:value => compute_change(@date_time_value, options), :params => (params ? params.dup : nil) )
99
+ PropertyValue::Date.new(timezone_finder,:value => @date_time_value.change(options), :params => (params ? params.dup : nil) )
110
100
  end
111
101
 
112
102
  def add_date_times_to(required_timezones) #:nodoc:
@@ -146,26 +136,30 @@ module RiCal
146
136
  date_time = self.to_ri_cal_date_time_value
147
137
  RiCal::OccurrencePeriod.new(date_time, date_time.advance(:hours => 24, :seconds => -1))
148
138
  end
149
-
139
+
150
140
  def start_of_day?
151
141
  true
152
142
  end
153
-
143
+
144
+ def to_floating_date_time_property
145
+ PropertyValue::DateTime.new(timezone_finder, :value => @date_time_value.ical_str)
146
+ end
147
+
154
148
  def to_zulu_occurrence_range_start_time
155
- to_ri_cal_date_time_value.to_zulu_occurrence_range_start_time
149
+ to_floating_date_time_property.to_zulu_occurrence_range_start_time
156
150
  end
157
-
151
+
158
152
  def to_zulu_occurrence_range_finish_time
159
153
  to_ri_cal_date_time_value.end_of_day.to_zulu_occurrence_range_finish_time
160
154
  end
161
-
155
+
162
156
  def to_finish_time
163
157
  to_ri_cal_date_time_value.end_of_day.to_datetime
164
158
  end
165
-
159
+
166
160
  def for_occurrence(occurrence)
167
161
  if occurrence.start_of_day?
168
- occurrence.to_ri_cal_date_value(timezone_finder)
162
+ occurrence.to_ri_cal_date_value(timezone_finder)
169
163
  else
170
164
  occurrence.for_parent(timezone_finder)
171
165
  end
@@ -5,32 +5,10 @@ module RiCal
5
5
  #
6
6
  # Methods for DateTime which support getting values at different point in time.
7
7
  module TimeMachine
8
- def compute_change(d, options) # :nodoc:
9
- ::DateTime.civil(
10
- options[:year] || d.year,
11
- options[:month] || d.month,
12
- options[:day] || d.day,
13
- options[:hour] || d.hour,
14
- options[:min] || (options[:hour] ? 0 : d.min),
15
- options[:sec] || ((options[:hour] || options[:min]) ? 0 : d.sec),
16
- options[:offset] || d.offset,
17
- options[:start] || d.start
18
- )
19
- end
20
-
21
- def compute_advance(d, options) # :nodoc:
22
- months_advance = (options[:years] || 0) * 12 + (options[:months] || 0)
23
- d = d >> months_advance unless months_advance == 0
24
- days_advance = (options[:weeks] || 0) * 7 + (options[:days] || 0)
25
- d = d + days_advance unless days_advance == 0
26
- datetime_advanced_by_date = compute_change(@date_time_value, :year => d.year, :month => d.month, :day => d.day)
27
- seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
28
- seconds_to_advance == 0 ? datetime_advanced_by_date : datetime_advanced_by_date + RiCal.RationalOffset[seconds_to_advance.round]
29
- end
30
8
 
31
9
  def advance(options) # :nodoc:
32
10
  PropertyValue::DateTime.new(timezone_finder,
33
- :value => compute_advance(@date_time_value, options),
11
+ :value => @date_time_value.advance(options),
34
12
  :tzid => @tzid,
35
13
  :params =>(params ? params.dup : nil)
36
14
  )
@@ -38,34 +16,34 @@ module RiCal
38
16
 
39
17
  def change(options) # :nodoc:
40
18
  PropertyValue::DateTime.new(timezone_finder,
41
- :value => compute_change(@date_time_value, options),
19
+ :value => @date_time_value.change(options),
42
20
  :tzid => @tzid,
43
21
  :params => (params ? params.dup : nil)
44
22
  )
45
23
  end
46
24
 
47
25
  def change_sec(new_sec) #:nodoc:
48
- PropertyValue::DateTime.civil(self.year, self.month, self.day, self.hour, self.min, sec, self.offset, self.start, params)
26
+ change(:sec => new_sec)
49
27
  end
50
28
 
51
29
  def change_min(new_min) #:nodoc:
52
- PropertyValue::DateTime.civil(self.year, self.month, self.day, self.hour, new_min, self.sec, self.offset, self.start, params)
30
+ change(:min => new_min)
53
31
  end
54
32
 
55
33
  def change_hour(new_hour) #:nodoc:
56
- PropertyValue::DateTime.civil(self.year, self.month, self.day, new_hour, self.min, self.sec, self.offset, self.start, params)
34
+ change(:hour => new_hour)
57
35
  end
58
36
 
59
37
  def change_day(new_day) #:nodoc:
60
- PropertyValue::DateTime.civil(self.year, self.month, new_day, self.hour, self.min, self.sec, self.offset, self.start, params)
38
+ change(:day => new_day)
61
39
  end
62
40
 
63
41
  def change_month(new_month) #:nodoc:
64
- PropertyValue::DateTime.civil(self.year, new_month, self.day, self.hour, self.min, self.sec, self.offset, self.start, params)
42
+ change(:month => new_month)
65
43
  end
66
44
 
67
45
  def change_year(new_year) #:nodoc:
68
- PropertyValue::DateTime.civil(new_year, self.month, self.day, self.hour, self.min, self.sec, self.offset, self.start, params)
46
+ change(:year => new_year)
69
47
  end
70
48
 
71
49
  # Return a DATE-TIME property representing the receiver on a different day (if necessary) so that
@@ -58,7 +58,7 @@ module RiCal
58
58
 
59
59
  def rational_tz_offset #:nodoc:
60
60
  if has_local_timezone?
61
- @rational_tz_offset ||= timezone.rational_utc_offset(@date_time_value)
61
+ @rational_tz_offset ||= timezone.rational_utc_offset(@date_time_value.to_datetime)
62
62
  else
63
63
  @rational_tz_offset ||= RiCal.RationalOffset[0]
64
64
  end
@@ -66,7 +66,7 @@ module RiCal
66
66
  # Returns the value of the receiver as an RFC 2445 iCalendar string
67
67
  def value
68
68
  if @date_time_value
69
- @date_time_value.strftime("%Y%m%dT%H%M%S#{tzid == "UTC" ? "Z" : ""}")
69
+ "#{@date_time_value.ical_str}#{tzid == "UTC" ? "Z" : ""}"
70
70
  else
71
71
  nil
72
72
  end
@@ -85,16 +85,18 @@ module RiCal
85
85
  when nil
86
86
  @date_time_value = nil
87
87
  when String
88
- @date_time_value = ::DateTime.parse(val)
88
+ @date_time_value = FastDateTime.from_date_time(::DateTime.parse(val))
89
89
  if val =~/Z/
90
90
  self.tzid = 'UTC'
91
91
  else
92
92
  @tzid ||= :floating
93
93
  end
94
- when ::DateTime
94
+ when FastDateTime
95
95
  @date_time_value = val
96
+ when ::DateTime
97
+ @date_time_value = FastDateTime.from_date_time(val)
96
98
  when ::Date, ::Time
97
- @date_time_value = ::DateTime.parse(val.to_s)
99
+ @date_time_value = FastDateTime.from_date_time(::DateTime.parse(val.to_s))
98
100
  end
99
101
  reset_cached_values
100
102
  end
@@ -173,7 +175,11 @@ module RiCal
173
175
  # Compare the receiver with another object which must respond to the to_datetime message
174
176
  # The comparison is done using the Ruby DateTime representations of the two objects
175
177
  def <=>(other)
176
- @date_time_value <=> other.to_datetime
178
+ other.cmp_fast_date_time_value(@date_time_value)
179
+ end
180
+
181
+ def cmp_fast_date_time_value(other)
182
+ other <=> @date_time_value
177
183
  end
178
184
 
179
185
  # Determine if the receiver and other are in the same month
@@ -181,12 +187,21 @@ module RiCal
181
187
  [other.year, other.month] == [year, month]
182
188
  end
183
189
 
190
+ def with_date_time_value(date_time_value)
191
+ PropertyValue::DateTime.new(
192
+ timezone_finder,
193
+ :value => date_time_value,
194
+ :params => (params),
195
+ :tzid => tzid
196
+ )
197
+ end
198
+
184
199
  def nth_wday_in_month(n, which_wday) #:nodoc:
185
- @date_time_value.nth_wday_in_month(n, which_wday, self)
200
+ with_date_time_value(@date_time_value.nth_wday_in_month(n, which_wday))
186
201
  end
187
202
 
188
203
  def nth_wday_in_year(n, which_wday) #:nodoc:
189
- @date_time_value.nth_wday_in_year(n, which_wday, self)
204
+ with_date_time_value(@date_time_value.nth_wday_in_year(n, which_wday))
190
205
  end
191
206
 
192
207
  def self.civil(year, month, day, hour, min, sec, offset, start, params) #:nodoc:
@@ -273,12 +288,12 @@ module RiCal
273
288
 
274
289
  # Return a Date property for this DateTime
275
290
  def to_ri_cal_date_value(timezone_finder=nil)
276
- PropertyValue::Date.new(timezone_finder, :value => @date_time_value.strftime("%Y%m%d"))
291
+ PropertyValue::Date.new(timezone_finder, :value => @date_time_value.ical_date_str)
277
292
  end
278
293
 
279
294
  # Return the Ruby DateTime representation of the receiver
280
295
  def to_datetime #:nodoc:
281
- @date_time_value
296
+ @date_time_value.to_datetime
282
297
  end
283
298
 
284
299
  # Returns a ruby DateTime object representing the receiver.
@@ -302,7 +317,7 @@ module RiCal
302
317
  # of the International Date Line
303
318
  def to_zulu_occurrence_range_start_time
304
319
  if floating?
305
- utc.advance(:hours => -12).to_datetime
320
+ @date_time_value.advance(:hours => -12, :offset => 0).to_datetime
306
321
  else
307
322
  to_zulu_time
308
323
  end
data/lib/ri_cal.rb CHANGED
@@ -14,7 +14,7 @@ module RiCal
14
14
  autoload :OccurrenceEnumerator, "#{my_dir}/ri_cal/occurrence_enumerator.rb"
15
15
 
16
16
  # :stopdoc:
17
- VERSION = '0.5.3'
17
+ VERSION = '0.6.0'
18
18
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
19
19
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
20
20