rrule 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/rrule.rb +1 -0
- data/lib/rrule/frequencies/frequency.rb +36 -2
- data/lib/rrule/frequencies/simple_weekly.rb +9 -0
- data/lib/rrule/rule.rb +4 -23
- data/rrule.gemspec +2 -2
- data/scripts/benchmark.rb +17 -0
- data/scripts/history.txt +5 -0
- data/spec/frequencies/daily_spec.rb +35 -28
- data/spec/frequencies/monthly_spec.rb +37 -31
- data/spec/frequencies/simple_weekly_spec.rb +30 -0
- data/spec/frequencies/weekly_spec.rb +58 -23
- data/spec/frequencies/yearly_spec.rb +31 -29
- data/spec/spec_helper.rb +2 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c26a3dfb1d12c01d066b7c664e6ea0da8fb5ead0
|
4
|
+
data.tar.gz: 1975eaa5dacd0363518d155f994a9966b837f682
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9f362bd929a06f539e69df842cebb0052f3f841b624d36e01edb9dca64e4c5f472da54b3d671df6089a991b6b4bd1b0bbe39502409274d5636ab68a81e6ed22
|
7
|
+
data.tar.gz: 70400ae4f025bcee80979056cfec688a16e5be6fd948a07d905fa9f5e48ec7d8f62df31d84f8d0181e001aa6ee27e89fb3c39250b6df85195eb91739876cc14a
|
data/README.md
CHANGED
data/lib/rrule.rb
CHANGED
@@ -8,6 +8,7 @@ module RRule
|
|
8
8
|
autoload :Frequency, 'rrule/frequencies/frequency'
|
9
9
|
autoload :Daily, 'rrule/frequencies/daily'
|
10
10
|
autoload :Weekly, 'rrule/frequencies/weekly'
|
11
|
+
autoload :SimpleWeekly, 'rrule/frequencies/simple_weekly'
|
11
12
|
autoload :Monthly, 'rrule/frequencies/monthly'
|
12
13
|
autoload :Yearly, 'rrule/frequencies/yearly'
|
13
14
|
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module RRule
|
2
2
|
class Frequency
|
3
|
-
attr_reader :current_date
|
3
|
+
attr_reader :current_date, :filters, :generator, :timeset
|
4
4
|
|
5
|
-
def initialize(context)
|
5
|
+
def initialize(context, filters, generator, timeset)
|
6
6
|
@context = context
|
7
7
|
@current_date = context.dtstart
|
8
|
+
@filters = filters
|
9
|
+
@generator = generator
|
10
|
+
@timeset = timeset
|
8
11
|
end
|
9
12
|
|
10
13
|
def advance
|
@@ -15,10 +18,41 @@ module RRule
|
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
21
|
+
def next_occurrences
|
22
|
+
possible_days_of_year = possible_days
|
23
|
+
|
24
|
+
if filters.present?
|
25
|
+
possible_days_of_year.each_with_index do |day_index, i|
|
26
|
+
possible_days_of_year[i] = nil if filters.any? { |filter| filter.reject?(day_index) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
generator.combine_dates_and_times(possible_days_of_year, timeset).tap do
|
31
|
+
advance
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
18
35
|
def possible_days
|
19
36
|
fail NotImplementedError
|
20
37
|
end
|
21
38
|
|
39
|
+
def self.for_options(options)
|
40
|
+
case options[:freq]
|
41
|
+
when 'DAILY'
|
42
|
+
Daily
|
43
|
+
when 'WEEKLY'
|
44
|
+
if options[:simple_weekly] && !options[:bymonth]
|
45
|
+
SimpleWeekly # simplified and faster version if we don't need to deal with filtering
|
46
|
+
else
|
47
|
+
Weekly
|
48
|
+
end
|
49
|
+
when 'MONTHLY'
|
50
|
+
Monthly
|
51
|
+
when 'YEARLY'
|
52
|
+
Yearly
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
22
56
|
private
|
23
57
|
|
24
58
|
attr_reader :context
|
data/lib/rrule/rule.rb
CHANGED
@@ -31,18 +31,6 @@ module RRule
|
|
31
31
|
count = options[:count]
|
32
32
|
|
33
33
|
filters = []
|
34
|
-
|
35
|
-
frequency = case options[:freq]
|
36
|
-
when 'DAILY'
|
37
|
-
Daily.new(context)
|
38
|
-
when 'WEEKLY'
|
39
|
-
Weekly.new(context)
|
40
|
-
when 'MONTHLY'
|
41
|
-
Monthly.new(context)
|
42
|
-
when 'YEARLY'
|
43
|
-
Yearly.new(context)
|
44
|
-
end
|
45
|
-
|
46
34
|
if options[:bymonth]
|
47
35
|
filters.push(ByMonth.new(options[:bymonth], context))
|
48
36
|
end
|
@@ -69,24 +57,17 @@ module RRule
|
|
69
57
|
generator = AllOccurrences.new(context)
|
70
58
|
end
|
71
59
|
|
60
|
+
frequency = Frequency.for_options(options).new(context, filters, generator, timeset)
|
61
|
+
|
72
62
|
loop do
|
73
63
|
return if frequency.current_date.year > MAX_YEAR
|
74
64
|
|
75
|
-
|
76
|
-
|
77
|
-
possible_days_of_year.each_with_index do |day_index, i|
|
78
|
-
possible_days_of_year[i] = nil if filters.any? { |filter| filter.reject?(day_index) }
|
79
|
-
end
|
80
|
-
|
81
|
-
results_with_time = generator.combine_dates_and_times(possible_days_of_year, timeset)
|
82
|
-
results_with_time.each do |this_result|
|
65
|
+
frequency.next_occurrences.each do |this_result|
|
83
66
|
next if this_result < dtstart
|
84
67
|
return if options[:until] && this_result > options[:until]
|
85
68
|
return if count && (count -= 1) < 0
|
86
69
|
yield this_result unless exdate.include?(this_result)
|
87
70
|
end
|
88
|
-
|
89
|
-
frequency.advance
|
90
71
|
end
|
91
72
|
end
|
92
73
|
|
@@ -99,7 +80,6 @@ module RRule
|
|
99
80
|
attr_reader :options
|
100
81
|
|
101
82
|
def floor_to_seconds(date)
|
102
|
-
return date
|
103
83
|
# This removes all sub-second and floors it to the second level.
|
104
84
|
# Sub-second level calculations breaks a lot of assumptions in this
|
105
85
|
# library and rounding it may also cause unexpected inequalities.
|
@@ -165,6 +145,7 @@ module RRule
|
|
165
145
|
when 'MONTHLY'
|
166
146
|
options[:bymonthday] = [dtstart.day]
|
167
147
|
when 'WEEKLY'
|
148
|
+
options[:simple_weekly] = true
|
168
149
|
options[:byweekday] = [Weekday.new(dtstart.wday)]
|
169
150
|
end
|
170
151
|
end
|
data/rrule.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rrule'
|
3
|
-
s.version = '0.
|
4
|
-
s.date = '
|
3
|
+
s.version = '0.3.0'
|
4
|
+
s.date = '2018-04-23'
|
5
5
|
s.summary = 'RRule expansion'
|
6
6
|
s.description = 'A gem for expanding dates according to the RRule specification'
|
7
7
|
s.authors = ['Ryan Mitchell']
|
@@ -0,0 +1,17 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '../lib/'))
|
2
|
+
require 'rrule'
|
3
|
+
include Benchmark
|
4
|
+
|
5
|
+
rules_to_benchmark = ['FREQ=WEEKLY', 'FREQ=WEEKLY;BYDAY=WE']
|
6
|
+
rrule_version = '0.3.0'
|
7
|
+
|
8
|
+
puts "Benchmarking rules in version #{rrule_version}: 1000 expansions over one month\n"
|
9
|
+
Benchmark.benchmark(CAPTION, rules_to_benchmark.map(&:size).max, FORMAT) do |bm|
|
10
|
+
rules_to_benchmark.each do |rule|
|
11
|
+
rrule = RRule.parse(rule, dtstart: Time.parse('Wed Jan 30 09:00:00 PST 2013'), tzid: 'America/Chicago')
|
12
|
+
bm.report(rule) do
|
13
|
+
1000.times { rrule.between(Time.parse('Sun Jul 31 22:00:00 PDT 2016'), Time.parse('Wed Aug 31 21:59:59 PDT 2016')) }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
puts "\n"
|
data/scripts/history.txt
ADDED
@@ -1,55 +1,62 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe RRule::Daily do
|
4
|
+
let(:interval) { 1 }
|
4
5
|
let(:context) do
|
5
6
|
RRule::Context.new(
|
6
|
-
{ interval:
|
7
|
+
{ interval: interval },
|
7
8
|
date,
|
8
9
|
'America/Los_Angeles'
|
9
10
|
)
|
10
11
|
end
|
12
|
+
let(:filters) { [] }
|
13
|
+
let(:generator) { RRule::AllOccurrences.new(context) }
|
14
|
+
let(:timeset) { [{ hour: date.hour, minute: date.min, second: date.sec }] }
|
11
15
|
|
12
|
-
|
13
|
-
subject { described_class.new(context).possible_days }
|
16
|
+
before { context.rebuild(date.year, date.month) }
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
describe '#next_occurrences' do
|
19
|
+
subject(:frequency) { described_class.new(context, filters, generator, timeset) }
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
context 'on a day in the first month' do
|
22
|
-
let(:date) { Date.new(1997, 1, 25)}
|
21
|
+
context 'with an interval of one' do
|
22
|
+
let(:date) { Time.zone.local(1997, 1, 1) }
|
23
23
|
|
24
|
-
it
|
24
|
+
it 'returns sequential days' do
|
25
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 1)]
|
26
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 2)]
|
27
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 3)]
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
|
-
context '
|
28
|
-
let(:
|
29
|
-
|
30
|
-
it { is_expected.to eql [55] }
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '#advance' do
|
35
|
-
subject { described_class.new(context).advance }
|
36
|
-
|
37
|
-
context 'on the first day of the year' do
|
38
|
-
let(:date) { Date.new(1997, 1, 1)}
|
31
|
+
context 'with an interval of two' do
|
32
|
+
let(:interval) { 2 }
|
33
|
+
let(:date) { Time.zone.local(1997, 1, 1) }
|
39
34
|
|
40
|
-
it
|
35
|
+
it 'returns every other day' do
|
36
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 1)]
|
37
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 3)]
|
38
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 5)]
|
39
|
+
end
|
41
40
|
end
|
42
41
|
|
43
42
|
context 'on the last day of February' do
|
44
|
-
let(:date) {
|
43
|
+
let(:date) { Time.zone.local(1997, 2, 28) }
|
45
44
|
|
46
|
-
it
|
45
|
+
it 'goes into the next month' do
|
46
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 2, 28)]
|
47
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 3, 1)]
|
48
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 3, 2)]
|
49
|
+
end
|
47
50
|
end
|
48
51
|
|
49
52
|
context 'on the last day of the year' do
|
50
|
-
let(:date) {
|
53
|
+
let(:date) { Time.zone.local(1997, 12, 31) }
|
51
54
|
|
52
|
-
it
|
55
|
+
it 'goes into the next year' do
|
56
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 12, 31)]
|
57
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1998, 1, 1)]
|
58
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1998, 1, 2)]
|
59
|
+
end
|
53
60
|
end
|
54
61
|
end
|
55
62
|
end
|
@@ -1,57 +1,63 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe RRule::Monthly do
|
4
|
+
let(:interval) { 1 }
|
4
5
|
let(:context) do
|
5
6
|
RRule::Context.new(
|
6
|
-
{ interval:
|
7
|
+
{ interval: interval },
|
7
8
|
date,
|
8
9
|
'America/Los_Angeles'
|
9
10
|
)
|
10
11
|
end
|
12
|
+
let(:filters) { [RRule::ByMonthDay.new([date.day], context)] }
|
13
|
+
let(:generator) { RRule::AllOccurrences.new(context) }
|
14
|
+
let(:timeset) { [{ hour: date.hour, minute: date.min, second: date.sec }] }
|
11
15
|
|
12
|
-
before
|
16
|
+
before { context.rebuild(date.year, date.month) }
|
13
17
|
|
14
|
-
describe '#
|
15
|
-
subject { described_class.new(context)
|
18
|
+
describe '#next_occurrences' do
|
19
|
+
subject(:frequency) { described_class.new(context, filters, generator, timeset) }
|
16
20
|
|
17
|
-
context '
|
18
|
-
let(:date) {
|
21
|
+
context 'with an interval of one' do
|
22
|
+
let(:date) { Time.zone.local(1997, 1, 1) }
|
19
23
|
|
20
|
-
it
|
24
|
+
it 'returns sequential months' do
|
25
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 1)]
|
26
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 2, 1)]
|
27
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 3, 1)]
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
|
-
context '
|
24
|
-
let(:
|
31
|
+
context 'with an interval of two' do
|
32
|
+
let(:interval) { 2 }
|
33
|
+
let(:date) { Time.zone.local(1997, 1, 1) }
|
25
34
|
|
26
|
-
it
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
it { is_expected.to eql (31..58).to_a }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#advance' do
|
37
|
-
subject { described_class.new(context).advance }
|
38
|
-
|
39
|
-
context 'on the first day of the year' do
|
40
|
-
let(:date) { Date.new(1997, 1, 1)}
|
41
|
-
|
42
|
-
it { is_expected.to eql date + 1.month }
|
35
|
+
it 'returns every other month' do
|
36
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 1)]
|
37
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 3, 1)]
|
38
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 5, 1)]
|
39
|
+
end
|
43
40
|
end
|
44
41
|
|
45
42
|
context 'on the last day of February' do
|
46
|
-
let(:date) {
|
43
|
+
let(:date) { Time.zone.local(1997, 2, 28) }
|
47
44
|
|
48
|
-
it
|
45
|
+
it 'returns the next three months' do
|
46
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 2, 28)]
|
47
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 3, 28)]
|
48
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 4, 28)]
|
49
|
+
end
|
49
50
|
end
|
50
51
|
|
51
52
|
context 'on the last day of the year' do
|
52
|
-
let(:date) {
|
53
|
-
|
54
|
-
it
|
53
|
+
let(:date) { Time.zone.local(1997, 12, 31) }
|
54
|
+
|
55
|
+
it 'returns empty arrays for periods with no matching occurrences' do
|
56
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 12, 31)]
|
57
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1998, 1, 31)]
|
58
|
+
expect(frequency.next_occurrences).to eql []
|
59
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1998, 3, 31)]
|
60
|
+
end
|
55
61
|
end
|
56
62
|
end
|
57
63
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RRule::SimpleWeekly do
|
4
|
+
let(:context) { RRule::Context.new({ interval: interval }, date, nil) }
|
5
|
+
let(:frequency) { described_class.new(context, nil, nil, nil) }
|
6
|
+
|
7
|
+
describe '#next_occurrences' do
|
8
|
+
let(:date) { Date.new(1997, 1, 1) }
|
9
|
+
|
10
|
+
context 'with an interval of 1' do
|
11
|
+
let(:interval) { 1 }
|
12
|
+
|
13
|
+
it 'returns occurrences every week' do
|
14
|
+
expect(frequency.next_occurrences).to eql [Date.new(1997, 1, 1)]
|
15
|
+
expect(frequency.next_occurrences).to eql [Date.new(1997, 1, 8)]
|
16
|
+
expect(frequency.next_occurrences).to eql [Date.new(1997, 1, 15)]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with an interval of 2' do
|
21
|
+
let(:interval) { 2 }
|
22
|
+
|
23
|
+
it 'returns occurrences every other week' do
|
24
|
+
expect(frequency.next_occurrences).to eql [Date.new(1997, 1, 1)]
|
25
|
+
expect(frequency.next_occurrences).to eql [Date.new(1997, 1, 15)]
|
26
|
+
expect(frequency.next_occurrences).to eql [Date.new(1997, 1, 29)]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,57 +1,92 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe RRule::Weekly do
|
4
|
+
let(:interval) { 1 }
|
4
5
|
let(:context) do
|
5
6
|
RRule::Context.new(
|
6
|
-
{ interval:
|
7
|
+
{ interval: interval, wkst: 1 },
|
7
8
|
date,
|
8
9
|
'America/Los_Angeles'
|
9
10
|
)
|
10
11
|
end
|
12
|
+
let(:filters) { [RRule::ByWeekDay.new([RRule::Weekday.new(date.wday)], context)] }
|
13
|
+
let(:generator) { RRule::AllOccurrences.new(context) }
|
14
|
+
let(:timeset) { [{ hour: date.hour, minute: date.min, second: date.sec }] }
|
11
15
|
|
12
|
-
before
|
16
|
+
before { context.rebuild(date.year, date.month) }
|
13
17
|
|
14
|
-
describe '#
|
15
|
-
subject { described_class.new(context)
|
18
|
+
describe '#next_occurrences' do
|
19
|
+
subject(:frequency) { described_class.new(context, filters, generator, timeset) }
|
16
20
|
|
17
|
-
context '
|
18
|
-
let(:date) {
|
21
|
+
context 'with an interval of one' do
|
22
|
+
let(:date) { Time.zone.local(1997, 1, 1) }
|
19
23
|
|
20
|
-
it
|
24
|
+
it 'returns sequential weeks' do
|
25
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 1)]
|
26
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 8)]
|
27
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 15)]
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
|
-
context '
|
24
|
-
let(:
|
31
|
+
context 'with an interval of two' do
|
32
|
+
let(:interval) { 2 }
|
33
|
+
let(:date) { Time.zone.local(1997, 1, 1) }
|
25
34
|
|
26
|
-
it
|
35
|
+
it 'returns every other week' do
|
36
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 1)]
|
37
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 15)]
|
38
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 29)]
|
39
|
+
end
|
27
40
|
end
|
28
41
|
|
29
|
-
context 'on
|
30
|
-
let(:date) {
|
42
|
+
context 'on the first day of the year with five days left in the week' do
|
43
|
+
let(:date) { Time.zone.local(1997, 1, 1) }
|
31
44
|
|
32
|
-
it
|
45
|
+
it 'returns the next three weeks' do
|
46
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 1)]
|
47
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 8)]
|
48
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 15)]
|
49
|
+
end
|
33
50
|
end
|
34
|
-
end
|
35
51
|
|
36
|
-
|
37
|
-
|
52
|
+
context 'on a day in the first month with two days left in the week' do
|
53
|
+
let(:date) { Time.zone.local(1997, 1, 25) }
|
54
|
+
|
55
|
+
it 'returns the next three weeks' do
|
56
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 25)]
|
57
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 2, 1)]
|
58
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 2, 8)]
|
59
|
+
end
|
60
|
+
end
|
38
61
|
|
39
|
-
context 'on the
|
40
|
-
let(:date) {
|
62
|
+
context 'on a day in the next month with six days left in the week' do
|
63
|
+
let(:date) { Time.zone.local(1997, 2, 25) }
|
41
64
|
|
42
|
-
it
|
65
|
+
it 'returns the next three weeks' do
|
66
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 2, 25)]
|
67
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 3, 4)]
|
68
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 3, 11)]
|
69
|
+
end
|
43
70
|
end
|
44
71
|
|
45
72
|
context 'on the last day of February' do
|
46
|
-
let(:date) {
|
73
|
+
let(:date) { Time.zone.local(1997, 2, 28) }
|
47
74
|
|
48
|
-
it
|
75
|
+
it 'returns the next three weeks' do
|
76
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 2, 28)]
|
77
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 3, 7)]
|
78
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 3, 14)]
|
79
|
+
end
|
49
80
|
end
|
50
81
|
|
51
82
|
context 'on the last day of the year' do
|
52
|
-
let(:date) {
|
83
|
+
let(:date) { Time.zone.local(1997, 12, 31) }
|
53
84
|
|
54
|
-
it
|
85
|
+
it 'returns the next three weeks' do
|
86
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 12, 31)]
|
87
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1998, 1, 7)]
|
88
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1998, 1, 14)]
|
89
|
+
end
|
55
90
|
end
|
56
91
|
end
|
57
92
|
end
|
@@ -1,52 +1,54 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe RRule::Yearly do
|
4
|
-
let(:
|
4
|
+
let(:interval) { 1 }
|
5
5
|
let(:context) do
|
6
6
|
RRule::Context.new(
|
7
|
-
{ interval:
|
7
|
+
{ interval: interval, wkst: 1 },
|
8
8
|
date,
|
9
9
|
'America/Los_Angeles'
|
10
10
|
)
|
11
11
|
end
|
12
|
+
let(:filters) { [RRule::ByMonth.new([date.month], context), RRule::ByMonthDay.new([date.day], context)] }
|
13
|
+
let(:generator) { RRule::AllOccurrences.new(context) }
|
14
|
+
let(:timeset) { [{ hour: date.hour, minute: date.min, second: date.sec }] }
|
12
15
|
|
13
|
-
before(:each) { context.rebuild(
|
16
|
+
before(:each) { context.rebuild(date.year, date.month) }
|
14
17
|
|
15
|
-
describe '#
|
16
|
-
subject { described_class.new(context)
|
17
|
-
|
18
|
-
context 'in a non leap year' do
|
19
|
-
before(:each) { context.rebuild(1997, 1) }
|
20
|
-
|
21
|
-
it { is_expected.to eql (0..364).to_a }
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'in a leap year' do
|
25
|
-
before(:each) { context.rebuild(2000, 1) }
|
26
|
-
|
27
|
-
it { is_expected.to eql (0..365).to_a }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe '#advance' do
|
32
|
-
subject { described_class.new(context).advance }
|
18
|
+
describe '#next_occurrences' do
|
19
|
+
subject(:frequency) { described_class.new(context, filters, generator, timeset) }
|
33
20
|
|
34
21
|
context 'on the first day of the year' do
|
35
|
-
let(:date) {
|
22
|
+
let(:date) { Time.zone.local(1997, 1, 1) }
|
36
23
|
|
37
|
-
it
|
24
|
+
it 'returns the next three years' do
|
25
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 1)]
|
26
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1998, 1, 1)]
|
27
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1999, 1, 1)]
|
28
|
+
end
|
38
29
|
end
|
39
30
|
|
40
|
-
context 'on the last day of February' do
|
41
|
-
let(:date) {
|
31
|
+
context 'on the last day of February in a leap year' do
|
32
|
+
let(:date) { Time.zone.local(2000, 2, 29) }
|
42
33
|
|
43
|
-
it
|
34
|
+
it 'skips non-leap years' do
|
35
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(2000, 2, 29)]
|
36
|
+
expect(frequency.next_occurrences).to eql []
|
37
|
+
expect(frequency.next_occurrences).to eql []
|
38
|
+
expect(frequency.next_occurrences).to eql []
|
39
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(2004, 2, 29)]
|
40
|
+
end
|
44
41
|
end
|
45
42
|
|
46
|
-
context '
|
47
|
-
let(:
|
43
|
+
context 'with an interval of two' do
|
44
|
+
let(:interval) { 2 }
|
45
|
+
let(:date) { Time.zone.local(1997, 1, 1) }
|
48
46
|
|
49
|
-
it
|
47
|
+
it 'returns every other year' do
|
48
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1997, 1, 1)]
|
49
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(1999, 1, 1)]
|
50
|
+
expect(frequency.next_occurrences).to eql [Time.zone.local(2001, 1, 1)]
|
51
|
+
end
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rrule
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Mitchell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- lib/rrule/frequencies/daily.rb
|
63
63
|
- lib/rrule/frequencies/frequency.rb
|
64
64
|
- lib/rrule/frequencies/monthly.rb
|
65
|
+
- lib/rrule/frequencies/simple_weekly.rb
|
65
66
|
- lib/rrule/frequencies/weekly.rb
|
66
67
|
- lib/rrule/frequencies/yearly.rb
|
67
68
|
- lib/rrule/generators/all_occurrences.rb
|
@@ -69,6 +70,8 @@ files:
|
|
69
70
|
- lib/rrule/rule.rb
|
70
71
|
- lib/rrule/weekday.rb
|
71
72
|
- rrule.gemspec
|
73
|
+
- scripts/benchmark.rb
|
74
|
+
- scripts/history.txt
|
72
75
|
- spec/context_spec.rb
|
73
76
|
- spec/filters/by_month_day_spec.rb
|
74
77
|
- spec/filters/by_month_spec.rb
|
@@ -77,6 +80,7 @@ files:
|
|
77
80
|
- spec/filters/by_year_day_spec.rb
|
78
81
|
- spec/frequencies/daily_spec.rb
|
79
82
|
- spec/frequencies/monthly_spec.rb
|
83
|
+
- spec/frequencies/simple_weekly_spec.rb
|
80
84
|
- spec/frequencies/weekly_spec.rb
|
81
85
|
- spec/frequencies/yearly_spec.rb
|
82
86
|
- spec/generators/all_occurrences_spec.rb
|
@@ -116,6 +120,7 @@ test_files:
|
|
116
120
|
- spec/filters/by_year_day_spec.rb
|
117
121
|
- spec/frequencies/daily_spec.rb
|
118
122
|
- spec/frequencies/monthly_spec.rb
|
123
|
+
- spec/frequencies/simple_weekly_spec.rb
|
119
124
|
- spec/frequencies/weekly_spec.rb
|
120
125
|
- spec/frequencies/yearly_spec.rb
|
121
126
|
- spec/generators/all_occurrences_spec.rb
|