ri_cal 0.6.3 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/README.txt +2 -0
- data/Rakefile +16 -1
- data/lib/ri_cal.rb +1 -1
- data/lib/ri_cal/component/calendar.rb +31 -15
- data/lib/ri_cal/component/event.rb +1 -1
- data/lib/ri_cal/core_extensions/date/conversions.rb +8 -0
- data/lib/ri_cal/core_extensions/date_time/conversions.rb +5 -0
- data/lib/ri_cal/core_extensions/time/conversions.rb +8 -11
- data/lib/ri_cal/fast_date_time.rb +12 -0
- data/lib/ri_cal/occurrence_enumerator.rb +34 -10
- data/lib/ri_cal/parser.rb +1 -1
- data/ri_cal.gemspec +2 -2
- data/spec/ri_cal/component/calendar_spec.rb +1 -0
- data/spec/ri_cal/component/event_spec.rb +99 -14
- data/spec/ri_cal/component/timezone_spec.rb +3 -3
- data/spec/ri_cal/occurrence_enumerator_spec.rb +39 -8
- data/tasks/spec.rake +25 -0
- metadata +2 -2
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 0.7.0 - 29 June 2009
|
2
|
+
* fixed http://rick_denatale.lighthouseapp.com/projects/30941/tickets/14
|
3
|
+
component without recurrence properties should enumerate just itself only if it is within the period between starting and before
|
4
|
+
* added the :overlapping option to OccurrenceEnumerator#occurrences - Allows the enumeration of occurrences which are either partiall or completely within a timespan given by a pair of Dates/Times/DateTimes
|
5
|
+
* Fixed some Ruby 1.9 incompatibilities
|
6
|
+
* Added some new rake tasks to run specs under multi-ruby
|
1
7
|
=== 0.6.3 - 14 June 2009
|
2
8
|
* Fixed http://rick_denatale.lighthouseapp.com/projects/30941-ri_cal/tickets/13
|
3
9
|
tzinfotimezones-with-no-transitions-fail-on-export
|
data/README.txt
CHANGED
@@ -326,6 +326,8 @@ In the case of unbounded components, you must either use the :count, or :before
|
|
326
326
|
or
|
327
327
|
|
328
328
|
event.occurrences(:before => Date.today >> 1)
|
329
|
+
|
330
|
+
Another option on the occurrences method is the :overlapping option, which takes an array of two Dates, Times or DateTimes which are expected to be in chronological order. Only events which occur either partially or fully within the range given by the :overlapping option will be enumerated.
|
329
331
|
|
330
332
|
Alternately, you can use the RiCal::OccurrenceEnumerator#each method,
|
331
333
|
or another Enumerable method (RiCal::OccurrenceEnumerator includes Enumerable), and terminate when you wish by breaking out of the block.
|
data/Rakefile
CHANGED
@@ -28,5 +28,20 @@ end
|
|
28
28
|
require 'newgem/tasks' # load /tasks/*.rake
|
29
29
|
Dir['tasks/**/*.rake'].each { |t| load t }
|
30
30
|
|
31
|
-
|
31
|
+
Rake::TaskManager.class_eval do
|
32
|
+
def remove_task(task_name)
|
33
|
+
@tasks.delete(task_name.to_s)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove_task(task_name)
|
38
|
+
Rake.application.remove_task(task_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Override existing test task to prevent integrations
|
42
|
+
# from being run unless specifically asked for
|
43
|
+
remove_task :test
|
44
|
+
task :test do
|
45
|
+
end
|
46
|
+
|
32
47
|
task :default => [:"spec:with_tzinfo_gem", :"spec:with_active_support"]
|
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.
|
17
|
+
VERSION = '0.7.0'
|
18
18
|
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
19
19
|
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
20
20
|
|
@@ -172,23 +172,39 @@ module RiCal
|
|
172
172
|
def string #:nodoc:
|
173
173
|
stream.string
|
174
174
|
end
|
175
|
-
|
176
|
-
|
177
|
-
string
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
175
|
+
|
176
|
+
if RUBY_VERSION =~ /^1\.9/
|
177
|
+
def utf8_safe_split(string, n)
|
178
|
+
if string.bytesize <= n
|
179
|
+
[string, nil]
|
180
|
+
else
|
181
|
+
bytes = string.bytes.to_a
|
182
|
+
while (128..191).include?(bytes[n])
|
183
|
+
n = n - 1
|
184
|
+
end
|
185
|
+
before = bytes[0,n]
|
186
|
+
after = bytes[n..-1]
|
187
|
+
[before.pack("C*").force_encoding("utf-8"), after.empty? ? nil : after.pack("C*").force_encoding("utf-8")]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
else
|
191
|
+
def valid_utf8?(string)
|
192
|
+
string.unpack("U") rescue nil
|
193
|
+
end
|
194
|
+
|
195
|
+
def utf8_safe_split(string, n)
|
196
|
+
if string.length <= n
|
197
|
+
[string, nil]
|
198
|
+
else
|
188
199
|
before = string[0, n]
|
189
200
|
after = string[n..-1]
|
190
|
-
|
191
|
-
|
201
|
+
until valid_utf8?(after)
|
202
|
+
n = n - 1
|
203
|
+
before = string[0, n]
|
204
|
+
after = string[n..-1]
|
205
|
+
end
|
206
|
+
[before, after.empty? ? nil : after]
|
207
|
+
end
|
192
208
|
end
|
193
209
|
end
|
194
210
|
|
@@ -29,7 +29,7 @@ module RiCal
|
|
29
29
|
dtstart_property ? dtstart.to_datetime : nil
|
30
30
|
end
|
31
31
|
|
32
|
-
# Return a
|
32
|
+
# Return a date_time_property representing the time at which the event ends
|
33
33
|
def finish_property
|
34
34
|
if dtend_property
|
35
35
|
dtend_property
|
@@ -23,6 +23,14 @@ module RiCal
|
|
23
23
|
to_ri_cal_date_value(timezone_finder)
|
24
24
|
end
|
25
25
|
|
26
|
+
def to_overlap_range_start
|
27
|
+
to_datetime
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_overlap_range_end
|
31
|
+
to_ri_cal_date_time_value.end_of_day.to_datetime
|
32
|
+
end
|
33
|
+
|
26
34
|
unless defined? ActiveSupport
|
27
35
|
# A method to keep Time, Date and DateTime instances interchangeable on conversions.
|
28
36
|
# In this case, it simply returns +self+.
|
@@ -22,6 +22,11 @@ module RiCal
|
|
22
22
|
to_ri_cal_date_time_value(timezone_finder)
|
23
23
|
end
|
24
24
|
|
25
|
+
def to_overlap_range_start
|
26
|
+
self
|
27
|
+
end
|
28
|
+
alias_method :to_overlap_range_end, :to_overlap_range_start
|
29
|
+
|
25
30
|
# Return a copy of this object which will be interpreted as a floating time.
|
26
31
|
def with_floating_timezone
|
27
32
|
dup.set_tzid(:floating)
|
@@ -21,23 +21,20 @@ module RiCal
|
|
21
21
|
to_ri_cal_date_time_value(timezone_finder)
|
22
22
|
end
|
23
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
|
+
|
24
30
|
# Return a copy of this object which will be interpreted as a floating time.
|
25
31
|
def with_floating_timezone
|
26
32
|
dup.set_tzid(:floating)
|
27
33
|
end
|
28
34
|
|
29
35
|
unless defined? ActiveSupport
|
30
|
-
|
31
|
-
|
32
|
-
# my_time = Time.now # => Mon Nov 12 23:04:21 -0500 2007
|
33
|
-
# my_time.to_datetime # => Mon, 12 Nov 2007 23:04:21 -0500
|
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_datetime # => Tue, 13 Jan 2009 13:13:03 -0500
|
37
|
-
def to_datetime
|
38
|
-
# 86400 is the number of seconds in a day
|
39
|
-
::DateTime.civil(year, month, day, hour, min, sec, RiCal.RationalOffset[utc_offset])
|
40
|
-
end
|
36
|
+
require 'date'
|
37
|
+
::Time.send(:public, :to_datetime)
|
41
38
|
end
|
42
39
|
end
|
43
40
|
end
|
@@ -20,6 +20,18 @@ module RiCal
|
|
20
20
|
def self.from_date_time(date_time)
|
21
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
22
|
end
|
23
|
+
|
24
|
+
def self.from_time(time)
|
25
|
+
new(time.year, time.month, time.day, time.hour, time.min, time.sec, (time.utc_offset.offset * SECONDS_IN_A_DAY))
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.from_date(date)
|
29
|
+
new(date.year, date.month, date.day, 0, 0, 0, 0)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.from_date_at_end_of_day(date)
|
33
|
+
new(date.year, date.month, date.day, 23, 59, 59, 0)
|
34
|
+
end
|
23
35
|
|
24
36
|
alias_method :utc_offset_seconds, :offset
|
25
37
|
|
@@ -96,7 +96,8 @@ module RiCal
|
|
96
96
|
|
97
97
|
# Also exclude occurrences before the :starting date_time
|
98
98
|
def before_start?(occurrence)
|
99
|
-
(@start && occurrence.dtstart.to_datetime < @start)
|
99
|
+
(@start && occurrence.dtstart.to_datetime < @start) ||
|
100
|
+
@overlap_range && occurrence.before_range?(@overlap_range)
|
100
101
|
end
|
101
102
|
|
102
103
|
def next_occurrence
|
@@ -118,7 +119,9 @@ module RiCal
|
|
118
119
|
|
119
120
|
def options_stop(occurrence)
|
120
121
|
occurrence != :excluded &&
|
121
|
-
(@cutoff && occurrence.dtstart.to_datetime >= @cutoff) ||
|
122
|
+
(@cutoff && occurrence.dtstart.to_datetime >= @cutoff) ||
|
123
|
+
(@count && @yielded >= @count) ||
|
124
|
+
(@overlap_range && occurrence.after_range?(@overlap_range))
|
122
125
|
end
|
123
126
|
|
124
127
|
|
@@ -127,30 +130,40 @@ module RiCal
|
|
127
130
|
def each(options = nil)
|
128
131
|
process_options(options) if options
|
129
132
|
if @rrules.empty?
|
130
|
-
|
133
|
+
unless before_start?(@component)
|
134
|
+
yield @component unless options_stop(@component)
|
135
|
+
end
|
131
136
|
else
|
132
137
|
occurrence = next_occurrence
|
133
138
|
while (occurrence)
|
134
|
-
|
139
|
+
candidate = @component.recurrence(occurrence)
|
140
|
+
if options_stop(candidate)
|
135
141
|
occurrence = nil
|
136
142
|
else
|
137
|
-
unless before_start?(
|
143
|
+
unless before_start?(candidate)
|
138
144
|
@yielded += 1
|
139
|
-
yield
|
145
|
+
yield candidate
|
140
146
|
end
|
141
147
|
occurrence = next_occurrence
|
142
148
|
end
|
143
149
|
end
|
144
150
|
end
|
145
151
|
end
|
146
|
-
|
152
|
+
|
147
153
|
def bounded?
|
148
|
-
@rrules.bounded? || @count || @cutoff
|
154
|
+
@rrules.bounded? || @count || @cutoff || @overlap_range
|
155
|
+
end
|
156
|
+
|
157
|
+
def process_overlap_range(overlap_range)
|
158
|
+
if overlap_range
|
159
|
+
@overlap_range = [overlap_range.first.to_overlap_range_start, overlap_range.last.to_overlap_range_end]
|
160
|
+
end
|
149
161
|
end
|
150
162
|
|
151
163
|
def process_options(options)
|
152
|
-
@start = options[:starting]
|
153
|
-
@cutoff = options[:before]
|
164
|
+
@start = options[:starting] && options[:starting].to_datetime
|
165
|
+
@cutoff = options[:before] && options[:before].to_datetime
|
166
|
+
@overlap_range = process_overlap_range(options[:overlapping])
|
154
167
|
@count = options[:count]
|
155
168
|
end
|
156
169
|
|
@@ -175,6 +188,7 @@ module RiCal
|
|
175
188
|
# * :starting:: a Date, Time, or DateTime, no occurrences starting before this argument will be returned
|
176
189
|
# * :before:: a Date, Time, or DateTime, no occurrences starting on or after this argument will be returned.
|
177
190
|
# * :count:: an integer which limits the number of occurrences returned.
|
191
|
+
# * :overlapping:: a two element array of Dates, Times, or DateTimes, assumed to be in chronological order. Only occurrences which are either totally or partially within the range will be returned.
|
178
192
|
def occurrences(options={})
|
179
193
|
enumeration_instance.to_a(options)
|
180
194
|
end
|
@@ -183,7 +197,17 @@ module RiCal
|
|
183
197
|
def enumeration_instance #:nodoc:
|
184
198
|
EnumerationInstance.new(self)
|
185
199
|
end
|
200
|
+
|
201
|
+
def before_range?(overlap_range)
|
202
|
+
finish = finish_time
|
203
|
+
!finish_time || finish_time < overlap_range.first
|
204
|
+
end
|
186
205
|
|
206
|
+
def after_range?(overlap_range)
|
207
|
+
start = start_time
|
208
|
+
!start || start > overlap_range.last
|
209
|
+
end
|
210
|
+
|
187
211
|
# execute the block for each occurrence
|
188
212
|
def each(&block) # :yields: Component
|
189
213
|
enumeration_instance.each(&block)
|
data/lib/ri_cal/parser.rb
CHANGED
data/ri_cal.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{ri_cal}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.7.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["author=Rick DeNatale"]
|
9
|
-
s.date = %q{2009-06-
|
9
|
+
s.date = %q{2009-06-29}
|
10
10
|
s.default_executable = %q{ri_cal}
|
11
11
|
s.description = %q{A new Ruby implementation of RFC2445 iCalendar.
|
12
12
|
|
@@ -1,9 +1,94 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
2
3
|
|
3
4
|
require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
|
4
5
|
|
5
6
|
describe RiCal::Component::Event do
|
6
7
|
|
8
|
+
context ".finish_time" do
|
9
|
+
it "should be the end of the start day for an event with a date dtstart and no dtend or duration" do
|
10
|
+
@it = RiCal.Event do |evt|
|
11
|
+
evt.dtstart = "20090704"
|
12
|
+
end
|
13
|
+
@it.finish_time.should == DateTime.parse("20090704T235959")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be the end of the end day for an event with a date dtstart and a dtend" do
|
17
|
+
@it = RiCal.Event do |evt|
|
18
|
+
evt.dtstart = "20090704"
|
19
|
+
evt.dtend = "20090706"
|
20
|
+
end
|
21
|
+
@it.finish_time.should == DateTime.parse("20090706T235959")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should be the start time for an event with a datetime dtstart and no dtend or duration" do
|
25
|
+
@it = RiCal.Event do |evt|
|
26
|
+
evt.dtstart = "20090704T013000Z"
|
27
|
+
end
|
28
|
+
@it.finish_time.should == DateTime.parse("20090704T013000Z")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be the end time for an event with a datetime dtend" do
|
32
|
+
@it = RiCal.Event do |evt|
|
33
|
+
evt.dtstart = "20090704"
|
34
|
+
evt.dtend = "20090706T120000"
|
35
|
+
end
|
36
|
+
@it.finish_time.should == DateTime.parse("20090706T120000")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be the end time for an event with a datetime dtstart and a duration" do
|
40
|
+
@it = RiCal.Event do |evt|
|
41
|
+
evt.dtstart = "20090704T120000Z"
|
42
|
+
evt.duration = "P1H30M"
|
43
|
+
end
|
44
|
+
@it.finish_time.should == DateTime.parse("20090704T133000Z")
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
context ".before_range?" do
|
50
|
+
context "with a Date dtstart and no dtend" do
|
51
|
+
before(:each) do
|
52
|
+
@it = RiCal.Event do |evt|
|
53
|
+
evt.dtstart = "20090704"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should be false if the range start is a date before the start date" do
|
58
|
+
@it.before_range?([Date.parse("20090703"), :anything]).should_not be
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should be false if the range start is the start date" do
|
62
|
+
@it.before_range?([Date.parse("20090704"), :anything]).should_not be
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should be true if the range start is a date after the start date" do
|
66
|
+
@it.before_range?([Date.parse("20090705"), :anything]).should be
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "with a Date dtstart and date dtend" do
|
71
|
+
before(:each) do
|
72
|
+
@it = RiCal.Event do |evt|
|
73
|
+
evt.dtstart = "20090704"
|
74
|
+
evt.dtend = "20090706"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should be false if the range start is a date before the end date" do
|
79
|
+
@it.before_range?([Date.parse("20090705"), :anything]).should_not be
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should be false if the range start is the end date" do
|
83
|
+
@it.before_range?([Date.parse("20090706"), :anything]).should_not be
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be true if the range start is a date after the end date" do
|
87
|
+
@it.before_range?([Date.parse("20090707"), :anything]).should be
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
7
92
|
context "bug report from Noboyuki Tomizawa" do
|
8
93
|
before(:each) do
|
9
94
|
|
@@ -512,7 +597,7 @@ describe RiCal::Component::Event do
|
|
512
597
|
end
|
513
598
|
|
514
599
|
it "should have the timezone in the ical representation of the exdate property" do
|
515
|
-
@event.exdate_property.to_s.should match(%r{;TZID=America/New_York[:;]})
|
600
|
+
@event.exdate_property.first.to_s.should match(%r{;TZID=America/New_York[:;]})
|
516
601
|
end
|
517
602
|
end
|
518
603
|
|
@@ -604,23 +689,23 @@ ENDCAL
|
|
604
689
|
end
|
605
690
|
end
|
606
691
|
|
607
|
-
|
692
|
+
context "An event with a floating start" do
|
608
693
|
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
end
|
694
|
+
before(:each) do
|
695
|
+
cal = RiCal.Calendar do |ical|
|
696
|
+
ical.event do |ievent|
|
697
|
+
ievent.dtstart "20090530T120000"
|
614
698
|
end
|
615
|
-
@event = cal.events.first
|
616
699
|
end
|
700
|
+
@event = cal.events.first
|
701
|
+
end
|
617
702
|
|
618
|
-
|
619
|
-
|
620
|
-
|
703
|
+
it "should produce a DateTime for dtstart" do
|
704
|
+
@event.dtstart.should be_instance_of(DateTime)
|
705
|
+
end
|
621
706
|
|
622
|
-
|
623
|
-
|
624
|
-
end
|
707
|
+
it "should have a floating dtstart" do
|
708
|
+
@event.dtstart.should have_floating_timezone
|
625
709
|
end
|
710
|
+
end
|
626
711
|
end
|
@@ -13,7 +13,7 @@ describe RiCal::Component::Timezone do
|
|
13
13
|
|
14
14
|
context "for a Timezone with no DST periods" do
|
15
15
|
before(:each) do
|
16
|
-
@it = RiCal.parse_string rectify_ical
|
16
|
+
@it = RiCal.parse_string rectify_ical(<<-'ENDCAL')
|
17
17
|
BEGIN:VTIMEZONE
|
18
18
|
TZID:Australia/Brisbane
|
19
19
|
X-LIC-LOCATION:Australia/Brisbane
|
@@ -37,7 +37,7 @@ describe RiCal::Component::Timezone do
|
|
37
37
|
|
38
38
|
context "from an iCal.app calendar for America/New_York starting March 11 2007" do
|
39
39
|
before(:each) do
|
40
|
-
@it = RiCal.parse_string rectify_ical
|
40
|
+
@it = RiCal.parse_string rectify_ical(<<-'ENDCAL')
|
41
41
|
BEGIN:VTIMEZONE
|
42
42
|
TZID:US/Eastern
|
43
43
|
BEGIN:DAYLIGHT
|
@@ -171,7 +171,7 @@ describe RiCal::Component::Timezone do
|
|
171
171
|
|
172
172
|
context "Bug report from paulsm" do
|
173
173
|
before(:each) do
|
174
|
-
cals = RiCal.parse_string rectify_ical
|
174
|
+
cals = RiCal.parse_string rectify_ical(<<-'ENDCAL')
|
175
175
|
BEGIN:VCALENDAR
|
176
176
|
X-WR-TIMEZONE:America/New_York
|
177
177
|
PRODID:-//Apple Inc.//iCal 3.0//EN
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
2
3
|
|
3
4
|
require File.join(File.dirname(__FILE__), %w[.. spec_helper.rb])
|
@@ -12,6 +13,7 @@ describe RiCal::OccurrenceEnumerator do
|
|
12
13
|
Fr13Unbounded_Zulu = <<-TEXT
|
13
14
|
BEGIN:VEVENT
|
14
15
|
DTSTART:19970902T090000Z
|
16
|
+
DTEND: 19970902T100000Z
|
15
17
|
EXDATE:19970902T090000Z
|
16
18
|
RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13
|
17
19
|
END:VEVENT
|
@@ -20,6 +22,7 @@ TEXT
|
|
20
22
|
Fr13Unbounded_Eastern = <<-TEXT
|
21
23
|
BEGIN:VEVENT
|
22
24
|
DTSTART;TZID=US-Eastern:19970902T090000
|
25
|
+
DTEND;TZID=US-Eastern:19970902T100000
|
23
26
|
EXDATE;TZID=US-Eastern:19970902T090000
|
24
27
|
RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13
|
25
28
|
END:VEVENT
|
@@ -30,10 +33,11 @@ TEXT
|
|
30
33
|
"19980313T090000Z",
|
31
34
|
"19981113T090000Z",
|
32
35
|
"19990813T090000Z",
|
33
|
-
"20001013T090000Z"
|
36
|
+
"20001013T090000Z"
|
34
37
|
].map {|start| src = <<-TEXT
|
35
38
|
BEGIN:VEVENT
|
36
39
|
DTSTART:#{start}
|
40
|
+
DTEND:#{start.gsub("T09","T10")}
|
37
41
|
RECURRENCE-ID:#{start}
|
38
42
|
END:VEVENT
|
39
43
|
TEXT
|
@@ -70,9 +74,36 @@ TEXT
|
|
70
74
|
result.map{|o|o.dtstart}.should == Fr13UnboundedZuluExpectedFive[0..2].map{|e| e.dtstart}
|
71
75
|
end
|
72
76
|
end
|
77
|
+
|
78
|
+
describe "with :overlapping specified" do
|
79
|
+
it "should include occurrences which overlap" do
|
80
|
+
result = @it.occurrences(:overlapping =>
|
81
|
+
[DateTime.parse("19981113T093000Z"), # occurrence[2].dtstart + 1/2 hour
|
82
|
+
DateTime.parse("20001013T083000Z")]) # occurrence[4].dtstart - 1/2 hour
|
83
|
+
result.map{|o|o.dtstart}.should == Fr13UnboundedZuluExpectedFive[2..3].map{|e| e.dtstart}
|
84
|
+
end
|
85
|
+
end
|
73
86
|
end
|
74
|
-
end
|
75
87
|
|
88
|
+
describe "for a non-recurring event" do
|
89
|
+
before(:each) do
|
90
|
+
@event_start = Time.now.utc
|
91
|
+
@event = RiCal.Event do |event|
|
92
|
+
event.dtstart = @event_start
|
93
|
+
event.dtend = @event_start + 3600
|
94
|
+
# event.rrule (no recurrence, single event)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should enumerate no occurrences if dtstart is before :starting" do
|
99
|
+
@event.occurrences(:starting => @event_start + 1).should be_empty
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should enumerate no occurrences if dtstart is after :before" do
|
103
|
+
@event.occurrences(:before => @event_start - 1).should be_empty
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
76
107
|
|
77
108
|
describe ".each" do
|
78
109
|
describe " for Every Friday the 13th, forever" do
|
@@ -156,7 +187,7 @@ TEXT
|
|
156
187
|
|
157
188
|
context "Ticket #4 from paulsm" do
|
158
189
|
it "should produce 4 occurrences" do
|
159
|
-
cal = RiCal.parse_string rectify_ical
|
190
|
+
cal = RiCal.parse_string rectify_ical(<<-ENDCAL)
|
160
191
|
BEGIN:VCALENDAR
|
161
192
|
METHOD:PUBLISH
|
162
193
|
PRODID:-//Apple Inc.//iCal 3.0//EN
|
@@ -188,7 +219,7 @@ TEXT
|
|
188
219
|
|
189
220
|
context "Ticket #2 from paulsm" do
|
190
221
|
before(:each) do
|
191
|
-
cals = RiCal.parse_string rectify_ical
|
222
|
+
cals = RiCal.parse_string rectify_ical(<<-ENDCAL)
|
192
223
|
BEGIN:VCALENDAR
|
193
224
|
X-WR-TIMEZONE:America/New_York
|
194
225
|
PRODID:-//Apple Inc.//iCal 3.0//EN
|
@@ -238,7 +269,7 @@ TEXT
|
|
238
269
|
|
239
270
|
context "Lighthouse bug #3" do
|
240
271
|
before(:each) do
|
241
|
-
cals = RiCal.parse_string rectify_ical
|
272
|
+
cals = RiCal.parse_string rectify_ical(<<-ENDCAL)
|
242
273
|
BEGIN:VCALENDAR
|
243
274
|
VERSION:2.0
|
244
275
|
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
|
@@ -282,7 +313,7 @@ TEXT
|
|
282
313
|
|
283
314
|
context "An event with a DATE dtstart, Ticket #6" do
|
284
315
|
before(:each) do
|
285
|
-
cal = RiCal.parse_string rectify_ical
|
316
|
+
cal = RiCal.parse_string rectify_ical(<<-ENDCAL)
|
286
317
|
BEGIN:VCALENDAR
|
287
318
|
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
|
288
319
|
VERSION:2.0
|
@@ -339,7 +370,7 @@ TEXT
|
|
339
370
|
end
|
340
371
|
context "bounded? bug" do
|
341
372
|
before(:each) do
|
342
|
-
events = RiCal.parse_string rectify_ical
|
373
|
+
events = RiCal.parse_string rectify_ical(<<-ENDCAL)
|
343
374
|
BEGIN:VEVENT
|
344
375
|
EXDATE:20090114T163000
|
345
376
|
EXDATE:20090128T163000
|
@@ -369,7 +400,7 @@ TEXT
|
|
369
400
|
|
370
401
|
context "EXDATES with timezones bug" do
|
371
402
|
before(:each) do
|
372
|
-
cals = RiCal.parse_string rectify_ical
|
403
|
+
cals = RiCal.parse_string rectify_ical(<<-ENDCAL)
|
373
404
|
BEGIN:VCALENDAR
|
374
405
|
METHOD:PUBLISH
|
375
406
|
PRODID:-//Apple Inc.//iCal 3.0//EN
|
data/tasks/spec.rake
CHANGED
@@ -35,6 +35,31 @@ namespace :spec do
|
|
35
35
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
36
36
|
t.ruby_opts << "-r #{File.join(File.dirname(__FILE__), *%w[gem_loader load_tzinfo_gem])}"
|
37
37
|
end
|
38
|
+
multiruby_path = `which multiruby`.chomp
|
39
|
+
if multiruby_path.length > 0 && Spec::Rake::SpecTask.instance_methods.include?("ruby_cmd")
|
40
|
+
namespace :multi do
|
41
|
+
desc "Run all specs with multiruby and ActiveSupport"
|
42
|
+
Spec::Rake::SpecTask.new(:with_active_support) do |t|
|
43
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
44
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
45
|
+
t.ruby_cmd = "#{multiruby_path}"
|
46
|
+
t.verbose = true
|
47
|
+
t.ruby_opts << "-r #{File.join(File.dirname(__FILE__), *%w[gem_loader load_active_support])}"
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Run all specs multiruby and the tzinfo gem"
|
51
|
+
Spec::Rake::SpecTask.new(:with_tzinfo_gem) do |t|
|
52
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
53
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
54
|
+
t.ruby_cmd = "#{multiruby_path}"
|
55
|
+
t.verbose = true
|
56
|
+
t.ruby_opts << "-r #{File.join(File.dirname(__FILE__), *%w[gem_loader load_tzinfo_gem])}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "run all specs under multiruby with ActiveSupport and also with the tzinfo gem"
|
61
|
+
task :multi => [:"spec:multi:with_active_support", :"spec:multi:with_tzinfo_gem"]
|
62
|
+
end
|
38
63
|
end
|
39
64
|
|
40
65
|
if RUBY_VERSION.match(/^1\.8\./)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ri_cal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- author=Rick DeNatale
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-29 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|