cyclical 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,218 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe MonthlyRule do
6
+ describe "simple rule" do
7
+ before do
8
+ @rule = MonthlyRule.new
9
+ end
10
+
11
+ it "should return one day as step" do
12
+ @rule.step.should == 1.month
13
+ end
14
+
15
+ it "should give next date" do
16
+ base = Time.local(2010, 1, 1, 9, 30, 21)
17
+
18
+ @rule.next(Time.local(2010, 1, 1), base).should == Time.local(2010, 1, 1, 9, 30, 21)
19
+ @rule.next(Time.local(2010, 1, 1, 9, 30, 21), base).should == Time.local(2010, 2, 1, 9, 30, 21)
20
+ @rule.next(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 2, 1, 9, 30, 21)
21
+
22
+ # align forward should include base time
23
+ @rule.next(base, base).should == base + 1.month
24
+ end
25
+
26
+ it "should give previous date" do
27
+ base = Time.local(2010, 1, 1, 9, 30, 21)
28
+
29
+ @rule.previous(Time.local(2010, 1, 1), base).should == Time.local(2009, 12, 1, 9, 30, 21)
30
+ @rule.previous(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 1, 9, 30, 21)
31
+
32
+ # align back should exclude base time
33
+ @rule.previous(base, base).should == Time.local(2009, 12, 1, 9, 30, 21)
34
+ end
35
+
36
+ it "should match dates" do
37
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should be_true
38
+
39
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 1, 9, 29)).should_not be_true
40
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 8, 9, 30)).should_not be_true
41
+ end
42
+ end
43
+
44
+ describe "finite rules" do
45
+ before do
46
+ @rule = MonthlyRule.new
47
+ end
48
+
49
+ it "should accept count and allow chaining" do
50
+ @rule.count(10).should be_a(MonthlyRule)
51
+ @rule.count.should == 10
52
+ end
53
+
54
+ it "should accept stop time" do
55
+ @rule.stop(Time.utc(2020, 1, 1)).should be_a(MonthlyRule)
56
+ @rule.stop.should == Time.utc(2020, 1, 1)
57
+ end
58
+
59
+ it "should report rule finiteness" do
60
+ MonthlyRule.new.count(5).should be_finite
61
+ MonthlyRule.new.stop(Time.utc(2020, 1, 1)).should be_finite
62
+
63
+ MonthlyRule.new.should_not be_finite
64
+ end
65
+ end
66
+
67
+ describe "rule with interval" do
68
+ before do
69
+ @every_other_month_rule = MonthlyRule.new(2)
70
+ @every_ten_months_rule = MonthlyRule.new(10)
71
+ end
72
+
73
+ it "should return corect step" do
74
+ @every_other_month_rule.step.should == 2.months
75
+ @every_ten_months_rule.step.should == 10.months
76
+ end
77
+
78
+ it "should find next date" do
79
+ base = Time.local(2010, 1, 1, 9, 30, 21)
80
+
81
+ @every_other_month_rule.next(Time.local(2010, 1, 1), base).should == Time.local(2010, 1, 1, 9, 30, 21)
82
+ @every_ten_months_rule.next(Time.local(2010, 1, 1), base).should == Time.local(2010, 1, 1, 9, 30, 21)
83
+
84
+ @every_other_month_rule.next(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 3, 1, 9, 30, 21)
85
+ @every_ten_months_rule.next(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 11, 1, 9, 30, 21)
86
+
87
+ # align forward should include base time
88
+ @every_other_month_rule.next(base, base).should == base + 2.months
89
+ @every_ten_months_rule.next(base, base).should == base + 10.months
90
+ end
91
+
92
+ it "should find previous date" do
93
+ base = Time.local(2010, 1, 1, 9, 30, 21)
94
+
95
+ @every_other_month_rule.previous(Time.local(2010, 1, 1), base).should == Time.local(2009, 11, 1, 9, 30, 21)
96
+ @every_ten_months_rule.previous(Time.local(2010, 1, 1), base).should == Time.local(2009, 3, 1, 9, 30, 21)
97
+
98
+ @every_other_month_rule.previous(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 1, 9, 30, 21)
99
+ @every_ten_months_rule.previous(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 1, 9, 30, 21)
100
+
101
+ # align back should exclude base time
102
+ @every_other_month_rule.previous(base, base).should == Time.local(2009, 11, 1, 9, 30, 21)
103
+ @every_ten_months_rule.previous(base, base).should == Time.local(2009, 3, 1, 9, 30, 21)
104
+ end
105
+
106
+ it "should match dates" do
107
+ # same month, same datetime
108
+ @every_ten_months_rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should be_true
109
+ @every_ten_months_rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should be_true
110
+
111
+ # right month, same dattime
112
+ @every_other_month_rule.match?(Time.local(2010, 3, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should be_true
113
+ @every_other_month_rule.match?(Time.local(2010, 11, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should be_true
114
+
115
+ # wrong month, same datetime
116
+ @every_ten_months_rule.match?(Time.local(2010, 2, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should_not be_true
117
+ @every_ten_months_rule.match?(Time.local(2010, 8, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should_not be_true
118
+
119
+ # right month, different datetime
120
+ @every_other_month_rule.match?(Time.local(2010, 3, 8, 9, 20), Time.local(2010, 1, 1, 9, 30)).should_not be_true
121
+ @every_other_month_rule.match?(Time.local(2010, 11, 21, 9, 35), Time.local(2010, 1, 1, 9, 30)).should_not be_true
122
+ end
123
+ end
124
+
125
+ describe "rule with filters" do
126
+ before do
127
+ @base = Time.utc(2000, 1, 1, 9, 30, 21)
128
+ @rule = Rule.monthly.months(1, 2).weekdays(1,3)
129
+ end
130
+
131
+ it "should find next date" do
132
+ @rule.next(Time.utc(2000, 1, 1), @base).should == Time.utc(2000, 1, 3, 9, 30, 21)
133
+ @rule.next(Time.utc(2000, 1, 3, 10), @base).should == Time.utc(2000, 1, 5, 9, 30, 21)
134
+
135
+ @rule.next(Time.utc(2000, 2, 2), @base).should == Time.utc(2000, 2, 2, 9, 30, 21)
136
+ @rule.next(Time.utc(2000, 2, 2, 10), @base).should == Time.utc(2000, 2, 7, 9, 30, 21)
137
+ @rule.next(Time.utc(2000, 2, 29), @base).should == Time.utc(2001, 1, 1, 9, 30, 21)
138
+ @rule.next(Time.utc(2000, 3, 1), @base).should == Time.utc(2001, 1, 1, 9, 30, 21)
139
+ end
140
+
141
+ it "should find previous date" do
142
+ @rule.previous(Time.utc(2000, 1, 1), @base).should == Time.utc(1999, 2, 24, 9, 30, 21)
143
+ @rule.previous(Time.utc(2000, 1, 3, 10), @base).should == Time.utc(2000, 1, 3, 9, 30, 21)
144
+
145
+ @rule.previous(Time.utc(2000, 2, 2), @base).should == Time.utc(2000, 1, 31, 9, 30, 21)
146
+ @rule.previous(Time.utc(2000, 2, 2, 10), @base).should == Time.utc(2000, 2, 2, 9, 30, 21)
147
+ @rule.previous(Time.utc(2000, 3, 3), @base).should == Time.utc(2000, 2, 28, 9, 30, 21)
148
+ @rule.previous(Time.utc(2000, 3, 1), @base).should == Time.utc(2000, 2, 28, 9, 30, 21)
149
+ end
150
+
151
+ it "should match dates" do
152
+ # weekdays match
153
+ @rule.match?(Time.utc(2000, 1, 3, 9, 30, 21), @base).should be_true
154
+ @rule.match?(Time.utc(2000, 1, 5, 9, 30, 21), @base).should be_true
155
+
156
+ @rule.match?(Time.utc(2000, 1, 4, 9, 30, 21), @base).should_not be_true
157
+ @rule.match?(Time.utc(2000, 1, 6, 9, 30, 21), @base).should_not be_true
158
+
159
+ # months match
160
+ @rule.match?(Time.utc(2000, 2, 23, 9, 30, 21), @base).should be_true
161
+ @rule.match?(Time.utc(2000, 2, 2, 9, 30, 21), @base).should be_true
162
+
163
+ @rule.match?(Time.utc(2000, 3, 3, 9, 30, 21), @base).should_not be_true
164
+ @rule.match?(Time.utc(2000, 3, 4, 9, 30, 21), @base).should_not be_true
165
+
166
+ # wrong time
167
+ @rule.match?(Time.utc(2000, 1, 3, 9, 30, 28), @base).should_not be_true
168
+ @rule.match?(Time.utc(2000, 1, 3, 9, 12, 29), @base).should_not be_true
169
+ @rule.match?(Time.utc(2000, 1, 3, 10, 30, 29), @base).should_not be_true
170
+ end
171
+ end
172
+
173
+ describe "serialization" do
174
+ it "should do a simple hash roundtrip" do
175
+ h = Rule.monthly(5).to_hash
176
+ restore = Rule.from_hash(h)
177
+
178
+ restore.class.should == MonthlyRule
179
+ restore.interval.should == 5
180
+ restore.step.should == 5.months
181
+ end
182
+
183
+ it "should do a hash roundtrip with count" do
184
+ h = Rule.monthly.count(10).to_hash
185
+ restore = Rule.from_hash(h)
186
+
187
+ restore.count.should == 10
188
+ end
189
+
190
+ it "should do a hash roundtrip with stop" do
191
+ h = Rule.monthly.stop(Time.local(2020, 10, 10)).to_hash
192
+ restore = Rule.from_hash(h)
193
+
194
+ restore.stop.should == Time.local(2020, 10, 10)
195
+ end
196
+
197
+ it "should do a hash roundtrip with weekdays filter" do
198
+ h = Rule.monthly.weekdays(:mon, :tuesday).to_hash
199
+ restore = Rule.from_hash(h)
200
+
201
+ restore.filters(:weekdays).weekdays.should == [1, 2]
202
+ end
203
+
204
+ it "should do a hash roundtrip with ordered weekdays filter" do
205
+ h = Rule.monthly.weekdays(:mon => 1, :tuesday => [2, -3]).to_hash
206
+ restore = Rule.from_hash(h)
207
+
208
+ restore.filters(:weekdays).ordered_weekdays.should == {:mo => [1], :tu => [-3, 2]}
209
+ end
210
+
211
+ it "should do a hash roundtrip with monthdays filter" do
212
+ h = Rule.monthly.monthdays(1, 3, 7, -10).to_hash
213
+ restore = Rule.from_hash(h)
214
+
215
+ restore.filters(:monthdays).monthdays.should == [-10, 1, 3, 7]
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ describe WeeklyRule do
4
+ describe "simple rule" do
5
+ before do
6
+ @rule = WeeklyRule.new
7
+ end
8
+
9
+ it "should return one week as step" do
10
+ @rule.step.should == 1.week
11
+ end
12
+
13
+ it "should find next date" do
14
+ base = Time.local(2010, 1, 1, 9, 30, 21)
15
+
16
+ @rule.next(Time.local(2010, 1, 1), base).should == Time.local(2010, 1, 1, 9, 30, 21)
17
+ @rule.next(Time.local(2010, 1, 1, 9, 30, 21), base).should == Time.local(2010, 1, 8, 9, 30, 21)
18
+ @rule.next(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 8, 9, 30, 21)
19
+
20
+ # align forward should include base time
21
+ @rule.next(base, base).should == base + 1.week
22
+ end
23
+
24
+ it "should find previous date" do
25
+ base = Time.local(2010, 1, 1, 9, 30, 21)
26
+
27
+ @rule.previous(Time.local(2010, 1, 1), base).should == Time.local(2009, 12, 25, 9, 30, 21)
28
+ @rule.previous(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 1, 9, 30, 21)
29
+
30
+ # align back should exclude base time
31
+ @rule.previous(base, base).should == Time.local(2009, 12, 25, 9, 30, 21)
32
+ end
33
+
34
+ it "should match dates" do
35
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 8, 9, 30)).should be_true
36
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 15, 9, 30)).should be_true
37
+
38
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 8, 9, 29)).should_not be_true
39
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 8, 10, 30)).should_not be_true
40
+ end
41
+ end
42
+
43
+ describe "finite rules" do
44
+ before do
45
+ @rule = WeeklyRule.new
46
+ end
47
+
48
+ it "should accept count and allow chaining" do
49
+ @rule.count(10).should be_a(WeeklyRule)
50
+ @rule.count.should == 10
51
+ end
52
+
53
+ it "should accept stop time" do
54
+ @rule.stop(Time.utc(2020, 1, 1)).should be_a(WeeklyRule)
55
+ @rule.stop.should == Time.utc(2020, 1, 1)
56
+ end
57
+
58
+ it "should report rule finiteness" do
59
+ WeeklyRule.new.count(5).should be_finite
60
+ WeeklyRule.new.stop(Time.utc(2020, 1, 1)).should be_finite
61
+
62
+ WeeklyRule.new.should_not be_finite
63
+ end
64
+ end
65
+
66
+ describe "rule with interval" do
67
+ before do
68
+ @every_other_week_rule = WeeklyRule.new(2)
69
+ @every_ten_weeks_rule = WeeklyRule.new(10)
70
+ end
71
+
72
+ it "should return corect step" do
73
+ @every_other_week_rule.step.should == 2.weeks
74
+ @every_ten_weeks_rule.step.should == 10.weeks
75
+ end
76
+
77
+ it "should find next date" do
78
+ base = Time.local(2010, 1, 1, 9, 30, 21)
79
+
80
+ @every_other_week_rule.next(Time.local(2010, 1, 1), base).should == Time.local(2010, 1, 1, 9, 30, 21)
81
+ @every_ten_weeks_rule.next(Time.local(2010, 1, 1), base).should == Time.local(2010, 1, 1, 9, 30, 21)
82
+
83
+ @every_other_week_rule.next(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 15, 9, 30, 21)
84
+ @every_ten_weeks_rule.next(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 3, 12, 9, 30, 21)
85
+
86
+ # align forward should include base time
87
+ @every_other_week_rule.next(base, base).should == base + 2.weeks
88
+ @every_ten_weeks_rule.next(base, base).should == base + 10.weeks
89
+ end
90
+
91
+ it "should align dates back" do
92
+ base = Time.local(2010, 1, 1, 9, 30, 21)
93
+
94
+ @every_other_week_rule.previous(Time.local(2010, 1, 1), base).should == Time.local(2009, 12, 18, 9, 30, 21)
95
+ @every_ten_weeks_rule.previous(Time.local(2010, 1, 1), base).localtime.should == Time.local(2009, 10, 23, 9, 30, 21)
96
+
97
+ @every_other_week_rule.previous(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 1, 9, 30, 21)
98
+ @every_ten_weeks_rule.previous(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 1, 9, 30, 21)
99
+
100
+ # align forward should include base time
101
+ @every_other_week_rule.previous(base, base).should == base - 2.weeks
102
+ @every_ten_weeks_rule.previous(base, base).should == base - 10.weeks
103
+ end
104
+
105
+ it "should check date alignment" do
106
+ base = Time.local(2010, 1, 1, 9, 30)
107
+
108
+ @every_other_week_rule.match?(Time.local(2010, 1, 1, 9, 30), base).should be_true
109
+ @every_other_week_rule.match?(Time.local(2010, 1, 15, 9, 30), base).should be_true
110
+
111
+ @every_ten_weeks_rule.match?(Time.local(2010, 1, 1, 9, 30), base).should be_true
112
+ @every_ten_weeks_rule.match?(Time.local(2010, 3, 12, 9, 30), base).should be_true
113
+
114
+ @every_other_week_rule.match?(Time.local(2010, 1, 2, 9, 30), base).should_not be_true
115
+ @every_ten_weeks_rule.match?(Time.local(2010, 1, 5, 9, 30), base).should_not be_true
116
+ end
117
+ end
118
+
119
+ describe "serialization" do
120
+ it "should do a simple hash roundtrip" do
121
+ h = Rule.weekly(5).to_hash
122
+ restore = Rule.from_hash(h)
123
+
124
+ restore.class.should == WeeklyRule
125
+ restore.interval.should == 5
126
+ restore.step.should == 5.weeks
127
+ end
128
+
129
+ it "should do a hash roundtrip with count" do
130
+ h = Rule.weekly.count(10).to_hash
131
+ restore = Rule.from_hash(h)
132
+
133
+ restore.count.should == 10
134
+ end
135
+
136
+ it "should do a hash roundtrip with stop" do
137
+ h = Rule.weekly.stop(Time.local(2020, 10, 10)).to_hash
138
+ restore = Rule.from_hash(h)
139
+
140
+ restore.stop.should == Time.local(2020, 10, 10)
141
+ end
142
+
143
+ it "should do a hash roundtrip with weekdays filter" do
144
+ h = Rule.weekly.weekdays(:mon, :tuesday).to_hash
145
+ restore = Rule.from_hash(h)
146
+
147
+ restore.filters(:weekdays).weekdays.should == [1, 2]
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,232 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe YearlyRule do
5
+ describe "simple rule" do
6
+ before do
7
+ @rule = YearlyRule.new
8
+ end
9
+
10
+ it "should return one day as step" do
11
+ @rule.step.should == 1.year
12
+ end
13
+
14
+ it "should give next date" do
15
+ base = Time.local(2010, 1, 1, 9, 30, 21)
16
+
17
+ @rule.next(Time.local(2010, 1, 1), base).should == Time.local(2010, 1, 1, 9, 30, 21)
18
+ @rule.next(Time.local(2010, 1, 1, 9, 30, 21), base).should == Time.local(2011, 1, 1, 9, 30, 21)
19
+ @rule.next(Time.local(2010, 1, 1, 10), base).should == Time.local(2011, 1, 1, 9, 30, 21)
20
+
21
+ # align forward should include base time
22
+ @rule.next(base, base).should == base + 1.year
23
+ end
24
+
25
+ it "should give previous date" do
26
+ base = Time.local(2010, 1, 1, 9, 30, 21)
27
+
28
+ @rule.previous(Time.local(2010, 1, 1), base).should == Time.local(2009, 1, 1, 9, 30, 21)
29
+ @rule.previous(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 1, 9, 30, 21)
30
+
31
+ # align back should exclude base time
32
+ @rule.previous(base, base).should == Time.local(2009, 1, 1, 9, 30, 21)
33
+ end
34
+
35
+ it "should match dates" do
36
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2011, 1, 1, 9, 30)).should be_true
37
+
38
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2011, 1, 1, 9, 29)).should_not be_true
39
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2011, 1, 2, 9, 30)).should_not be_true
40
+ @rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2011, 2, 1, 9, 30)).should_not be_true
41
+ end
42
+ end
43
+
44
+ describe "finite rules" do
45
+ before do
46
+ @rule = YearlyRule.new
47
+ end
48
+
49
+ it "should accept count and allow chaining" do
50
+ @rule.count(10).should be_a(YearlyRule)
51
+ @rule.count.should == 10
52
+ end
53
+
54
+ it "should accept stop time" do
55
+ @rule.stop(Time.utc(2020, 1, 1)).should be_a(YearlyRule)
56
+ @rule.stop.should == Time.utc(2020, 1, 1)
57
+ end
58
+
59
+ it "should report rule finiteness" do
60
+ YearlyRule.new.count(5).should be_finite
61
+ YearlyRule.new.stop(Time.utc(2020, 1, 1)).should be_finite
62
+
63
+ YearlyRule.new.should_not be_finite
64
+ end
65
+ end
66
+
67
+ describe "rule with interval" do
68
+ before do
69
+ @every_other_year_rule = YearlyRule.new(2)
70
+ @every_ten_years_rule = YearlyRule.new(10)
71
+ end
72
+
73
+ it "should return corect step" do
74
+ @every_other_year_rule.step.should == 2.years
75
+ @every_ten_years_rule.step.should == 10.years
76
+ end
77
+
78
+ it "should find next date" do
79
+ base = Time.local(2010, 1, 1, 9, 30, 21)
80
+
81
+ @every_other_year_rule.next(Time.local(2010, 1, 1), base).should == Time.local(2010, 1, 1, 9, 30, 21)
82
+ @every_ten_years_rule.next(Time.local(2010, 1, 1), base).should == Time.local(2010, 1, 1, 9, 30, 21)
83
+
84
+ @every_other_year_rule.next(Time.local(2010, 1, 1, 10), base).should == Time.local(2012, 1, 1, 9, 30, 21)
85
+ @every_ten_years_rule.next(Time.local(2010, 1, 1, 10), base).should == Time.local(2020, 1, 1, 9, 30, 21)
86
+
87
+ # align forward should include base time
88
+ @every_other_year_rule.next(base, base).should == base + 2.years
89
+ @every_ten_years_rule.next(base, base).should == base + 10.years
90
+ end
91
+
92
+ it "should find previous date" do
93
+ base = Time.local(2010, 1, 1, 9, 30, 21)
94
+
95
+ @every_other_year_rule.previous(Time.local(2010, 1, 1), base).should == Time.local(2008, 1, 1, 9, 30, 21)
96
+ @every_ten_years_rule.previous(Time.local(2010, 1, 1), base).should == Time.local(2000, 1, 1, 9, 30, 21)
97
+
98
+ @every_other_year_rule.previous(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 1, 9, 30, 21)
99
+ @every_ten_years_rule.previous(Time.local(2010, 1, 1, 10), base).should == Time.local(2010, 1, 1, 9, 30, 21)
100
+
101
+ # align back should exclude base time
102
+ @every_other_year_rule.previous(base, base).should == Time.local(2008, 1, 1, 9, 30, 21)
103
+ @every_ten_years_rule.previous(base, base).should == Time.local(2000, 1, 1, 9, 30, 21)
104
+ end
105
+
106
+ it "should match dates" do
107
+ # same year, same datetime
108
+ @every_ten_years_rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should be_true
109
+ @every_ten_years_rule.match?(Time.local(2010, 1, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should be_true
110
+
111
+ # right year, same dattime
112
+ @every_other_year_rule.match?(Time.local(2012, 1, 12, 9, 30), Time.local(2010, 1, 12, 9, 30)).should be_true
113
+ @every_other_year_rule.match?(Time.local(2020, 1, 12, 9, 30), Time.local(2010, 1, 12, 9, 30)).should be_true
114
+
115
+ # wrong year, same datetime
116
+ @every_ten_years_rule.match?(Time.local(2011, 1, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should_not be_true
117
+ @every_ten_years_rule.match?(Time.local(2015, 1, 1, 9, 30), Time.local(2010, 1, 1, 9, 30)).should_not be_true
118
+
119
+ # right year, different datetime
120
+ @every_other_year_rule.match?(Time.local(2012, 3, 8, 9, 20), Time.local(2010, 1, 12, 9, 30)).should_not be_true
121
+ @every_other_year_rule.match?(Time.local(2020, 6, 21, 9, 35), Time.local(2010, 1, 12, 9, 30)).should_not be_true
122
+ end
123
+ end
124
+
125
+ describe "rule with filters" do
126
+ before do
127
+ @base = Time.utc(2000, 1, 1, 9, 30, 21)
128
+ @rule = Rule.yearly.months(1, 2).weekdays(1,3)
129
+ end
130
+
131
+ it "should find next date" do
132
+ @rule.next(Time.utc(2000, 1, 1), @base).should == Time.utc(2000, 1, 3, 9, 30, 21)
133
+ @rule.next(Time.utc(2000, 1, 3, 10), @base).should == Time.utc(2000, 1, 5, 9, 30, 21)
134
+
135
+ @rule.next(Time.utc(2000, 2, 2), @base).should == Time.utc(2000, 2, 2, 9, 30, 21)
136
+ @rule.next(Time.utc(2000, 2, 2, 10), @base).should == Time.utc(2000, 2, 7, 9, 30, 21)
137
+ @rule.next(Time.utc(2000, 2, 29), @base).should == Time.utc(2001, 1, 1, 9, 30, 21)
138
+ @rule.next(Time.utc(2000, 3, 1), @base).should == Time.utc(2001, 1, 1, 9, 30, 21)
139
+ end
140
+
141
+ it "should find previous date" do
142
+ @rule.previous(Time.utc(2000, 1, 1), @base).should == Time.utc(1999, 2, 24, 9, 30, 21)
143
+ @rule.previous(Time.utc(2000, 1, 3, 10), @base).should == Time.utc(2000, 1, 3, 9, 30, 21)
144
+
145
+ @rule.previous(Time.utc(2000, 2, 2), @base).should == Time.utc(2000, 1, 31, 9, 30, 21)
146
+ @rule.previous(Time.utc(2000, 2, 2, 10), @base).should == Time.utc(2000, 2, 2, 9, 30, 21)
147
+ @rule.previous(Time.utc(2000, 3, 3), @base).should == Time.utc(2000, 2, 28, 9, 30, 21)
148
+ @rule.previous(Time.utc(2000, 3, 1), @base).should == Time.utc(2000, 2, 28, 9, 30, 21)
149
+ end
150
+
151
+ it "should match dates" do
152
+ # weekdays match
153
+ @rule.match?(Time.utc(2000, 1, 3, 9, 30, 21), @base).should be_true
154
+ @rule.match?(Time.utc(2000, 1, 5, 9, 30, 21), @base).should be_true
155
+
156
+ @rule.match?(Time.utc(2000, 1, 4, 9, 30, 21), @base).should_not be_true
157
+ @rule.match?(Time.utc(2000, 1, 6, 9, 30, 21), @base).should_not be_true
158
+
159
+ # months match
160
+ @rule.match?(Time.utc(2000, 2, 23, 9, 30, 21), @base).should be_true
161
+ @rule.match?(Time.utc(2000, 2, 2, 9, 30, 21), @base).should be_true
162
+
163
+ @rule.match?(Time.utc(2000, 3, 3, 9, 30, 21), @base).should_not be_true
164
+ @rule.match?(Time.utc(2000, 3, 4, 9, 30, 21), @base).should_not be_true
165
+
166
+ # wrong time
167
+ @rule.match?(Time.utc(2000, 1, 3, 9, 30, 28), @base).should_not be_true
168
+ @rule.match?(Time.utc(2000, 1, 3, 9, 12, 29), @base).should_not be_true
169
+ @rule.match?(Time.utc(2000, 1, 3, 10, 30, 29), @base).should_not be_true
170
+ end
171
+ end
172
+
173
+ describe "serialization" do
174
+ it "should do a hash roundtrip" do
175
+ h = Rule.yearly(5).to_hash
176
+ restore = Rule.from_hash(h)
177
+
178
+ restore.class.should == YearlyRule
179
+ restore.interval.should == 5
180
+ restore.step.should == 5.years
181
+ end
182
+
183
+ it "should do a hash roundtrip with count" do
184
+ h = Rule.yearly.count(10).to_hash
185
+ restore = Rule.from_hash(h)
186
+
187
+ restore.count.should == 10
188
+ end
189
+
190
+ it "should do a hash roundtrip with stop" do
191
+ h = Rule.yearly.stop(Time.local(2020, 10, 10)).to_hash
192
+ restore = Rule.from_hash(h)
193
+
194
+ restore.stop.should == Time.local(2020, 10, 10)
195
+ end
196
+
197
+ it "should do a hash roundtrip with weekdays filter" do
198
+ h = Rule.yearly.weekdays(:mon, :tuesday).to_hash
199
+ restore = Rule.from_hash(h)
200
+
201
+ restore.filters(:weekdays).weekdays.should == [1, 2]
202
+ end
203
+
204
+ it "should do a hash roundtrip with ordered weekdays filter" do
205
+ h = Rule.yearly.weekdays(:mon => 1, :tuesday => [2, -3]).to_hash
206
+ restore = Rule.from_hash(h)
207
+
208
+ restore.filters(:weekdays).ordered_weekdays.should == {:mo => [1], :tu => [-3, 2]}
209
+ end
210
+
211
+ it "should do a hash roundtrip with monthdays filter" do
212
+ h = Rule.yearly.monthdays(1, 3, 7, -10).to_hash
213
+ restore = Rule.from_hash(h)
214
+
215
+ restore.filters(:monthdays).monthdays.should == [-10, 1, 3, 7]
216
+ end
217
+
218
+ it "should do a hash roundtrip with months filter" do
219
+ h = Rule.yearly.months(1, 3, 12, -5).to_hash
220
+ restore = Rule.from_hash(h)
221
+
222
+ restore.filters(:months).months.should == [-5, 1, 3, 12]
223
+ end
224
+
225
+ it "should do a hash roundtrip with yeardays filter" do
226
+ h = Rule.yearly.yeardays(1, 30, 120, -50).to_hash
227
+ restore = Rule.from_hash(h)
228
+
229
+ restore.filters(:yeardays).yeardays.should == [-50, 1, 30, 120]
230
+ end
231
+ end
232
+ end