by_star 2.2.1 → 3.0.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.
Files changed (55) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +5 -5
  3. data/.travis.yml +61 -35
  4. data/CHANGELOG.md +44 -35
  5. data/Gemfile +18 -25
  6. data/MIT-LICENSE +20 -20
  7. data/README.md +577 -540
  8. data/Rakefile +18 -18
  9. data/UPGRADING +6 -12
  10. data/by_star.gemspec +34 -32
  11. data/cleaner.rb +24 -24
  12. data/lib/by_star.rb +17 -16
  13. data/lib/by_star/base.rb +68 -70
  14. data/lib/by_star/between.rb +156 -120
  15. data/lib/by_star/directional.rb +37 -33
  16. data/lib/by_star/kernel/date.rb +50 -19
  17. data/lib/by_star/kernel/time.rb +41 -41
  18. data/lib/by_star/normalization.rb +127 -118
  19. data/lib/by_star/orm/active_record/by_star.rb +61 -69
  20. data/lib/by_star/orm/mongoid/by_star.rb +76 -73
  21. data/lib/by_star/orm/mongoid/reorder.rb +23 -0
  22. data/lib/by_star/version.rb +3 -3
  23. data/spec/database.yml +15 -15
  24. data/spec/fixtures/active_record/models.rb +12 -10
  25. data/spec/fixtures/active_record/schema.rb +19 -19
  26. data/spec/fixtures/mongoid/models.rb +31 -29
  27. data/spec/fixtures/shared/seeds.rb +26 -26
  28. data/spec/gemfiles/Gemfile.master +6 -0
  29. data/spec/gemfiles/Gemfile.rails40 +7 -0
  30. data/spec/gemfiles/Gemfile.rails41 +7 -0
  31. data/spec/gemfiles/Gemfile.rails42 +7 -0
  32. data/spec/gemfiles/Gemfile.rails50 +10 -0
  33. data/spec/gemfiles/Gemfile.rails51 +10 -0
  34. data/spec/integration/active_record/active_record_spec.rb +38 -53
  35. data/spec/integration/mongoid/mongoid_spec.rb +37 -46
  36. data/spec/integration/shared/between_times.rb +82 -0
  37. data/spec/integration/shared/by_calendar_month.rb +55 -55
  38. data/spec/integration/shared/by_cweek.rb +54 -0
  39. data/spec/integration/shared/by_day.rb +96 -108
  40. data/spec/integration/shared/by_direction.rb +172 -153
  41. data/spec/integration/shared/by_fortnight.rb +48 -48
  42. data/spec/integration/shared/by_month.rb +50 -50
  43. data/spec/integration/shared/by_quarter.rb +49 -49
  44. data/spec/integration/shared/by_week.rb +54 -54
  45. data/spec/integration/shared/by_weekend.rb +49 -49
  46. data/spec/integration/shared/by_year.rb +48 -48
  47. data/spec/integration/shared/offset_parameter.rb +32 -31
  48. data/spec/integration/shared/order_parameter.rb +36 -0
  49. data/spec/integration/shared/relative.rb +174 -174
  50. data/spec/integration/shared/scope_parameter.rb +73 -72
  51. data/spec/spec_helper.rb +29 -29
  52. data/spec/unit/kernel_date_spec.rb +113 -60
  53. data/spec/unit/kernel_time_spec.rb +57 -57
  54. data/spec/unit/normalization_spec.rb +305 -255
  55. metadata +61 -62
@@ -1,255 +1,305 @@
1
- require 'spec_helper'
2
-
3
- describe ByStar::Normalization do
4
-
5
- let(:options){ {} }
6
-
7
- shared_examples_for 'time normalization from string' do
8
-
9
- context 'when Chronic is defined' do
10
-
11
- context 'date String' do
12
- let(:input){ '2014-01-01' }
13
- it { should eq Time.zone.parse('2014-01-01 12:00:00') }
14
- end
15
-
16
- context 'time String' do
17
- let(:input){ '2014-01-01 15:00:00' }
18
- it { should eq Time.zone.parse('2014-01-01 15:00:00') }
19
- end
20
-
21
- context 'natural language String' do
22
- let(:input){ 'tomorrow at 3:30 pm' }
23
- it { should eq Time.zone.parse('2014-01-02 15:30:00') }
24
- end
25
- end
26
-
27
- context 'when Chronic is not defined' do
28
-
29
- before { hide_const('Chronic') }
30
-
31
- context 'date String' do
32
- let(:input){ '2014-01-01' }
33
- it { should eq Time.zone.parse('2014-01-01 00:00:00') }
34
- end
35
-
36
- context 'time String' do
37
- let(:input){ '2014-01-01 15:00:00' }
38
- it { should eq Time.zone.parse('2014-01-01 15:00:00') }
39
- end
40
-
41
- context 'natural language String' do
42
- let(:input){ 'tomorrow at noon' }
43
- it { ->{subject}.should raise_error(ByStar::ParseError, "Cannot parse String #{input.inspect}") }
44
- end
45
- end
46
- end
47
-
48
- shared_examples_for 'time normalization from date/time' do
49
- context 'Date' do
50
- let(:input){ Date.parse('2014-01-01') }
51
- it { should eq Time.zone.parse('2014-01-01 00:00:00') }
52
- end
53
-
54
- context 'DateTime' do
55
- let(:input){ Time.zone.parse('2014-01-01 15:00:00').to_datetime }
56
- it { should eq Time.zone.parse('2014-01-01 15:00:00') }
57
- end
58
-
59
- context 'Time' do
60
- let(:input){ Time.zone.parse('2014-01-01 15:00:00') }
61
- it { should eq Time.zone.parse('2014-01-01 15:00:00') }
62
- end
63
- end
64
-
65
- describe '#time' do
66
- subject { ByStar::Normalization.time(input) }
67
- it_behaves_like 'time normalization from string'
68
- it_behaves_like 'time normalization from date/time'
69
- end
70
-
71
- describe '#week' do
72
- subject { ByStar::Normalization.week(input, options) }
73
- it_behaves_like 'time normalization from string'
74
- it_behaves_like 'time normalization from date/time'
75
-
76
- context 'Fixnum 0' do
77
- let(:input){ 0 }
78
- it { should eq Time.zone.parse('2014-01-01 00:00:00') }
79
- end
80
-
81
- context 'Fixnum 20' do
82
- let(:input){ 20 }
83
- it { should eq Time.zone.parse('2014-05-21 00:00:00') }
84
- end
85
-
86
- context 'with year option' do
87
- let(:options){ { :year => 2011 } }
88
-
89
- context 'Fixnum 0' do
90
- let(:input){ 0 }
91
- it { should eq Time.zone.parse('2011-01-01 00:00:00') }
92
- end
93
-
94
- context 'Fixnum 20' do
95
- let(:input){ 20 }
96
- it { should eq Time.zone.parse('2011-05-21 00:00:00') }
97
- end
98
- end
99
- end
100
-
101
- describe '#fortnight' do
102
- subject { ByStar::Normalization.fortnight(input, options) }
103
- it_behaves_like 'time normalization from string'
104
- it_behaves_like 'time normalization from date/time'
105
-
106
- context 'Fixnum 0' do
107
- let(:input){ 0 }
108
- it { should eq Time.zone.parse('2014-01-01 00:00:00') }
109
- end
110
-
111
- context 'Fixnum 26' do
112
- let(:input){ 26 }
113
- it { should eq Time.zone.parse('2014-12-31 00:00:00') }
114
- end
115
-
116
- context 'out of range' do
117
- specify { ->{ ByStar::Normalization.fortnight(-1) }.should raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
118
- specify { ->{ ByStar::Normalization.fortnight(27) }.should raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
119
- end
120
-
121
- context 'with year option' do
122
- let(:options){ { :year => 2011 } }
123
-
124
- context 'Fixnum 0' do
125
- let(:input){ 0 }
126
- it { should eq Time.zone.parse('2011-01-01 00:00:00') }
127
- end
128
-
129
- context 'Fixnum 26' do
130
- let(:input){ 26 }
131
- it { should eq Time.zone.parse('2011-12-31 00:00:00') }
132
- end
133
- end
134
- end
135
-
136
- describe '#month' do
137
- subject { ByStar::Normalization.month(input, options) }
138
- it_behaves_like 'time normalization from date/time'
139
-
140
- context 'month abbr String' do
141
- let(:input){ 'Feb' }
142
- it { should eq Time.zone.parse('2014-02-01 00:00:00') }
143
- end
144
-
145
- context 'month full String' do
146
- let(:input){ 'February' }
147
- it { should eq Time.zone.parse('2014-02-01 00:00:00') }
148
- end
149
-
150
- context 'number String' do
151
- let(:input){ '2' }
152
- it { should eq Time.zone.parse('2014-02-01 00:00:00') }
153
- end
154
-
155
- context 'Fixnum' do
156
- let(:input){ 2 }
157
- it { should eq Time.zone.parse('2014-02-01 00:00:00') }
158
- end
159
-
160
- context 'out of range' do
161
- specify { ->{ ByStar::Normalization.month(0) }.should raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
162
- specify { ->{ ByStar::Normalization.month(13) }.should raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
163
- end
164
-
165
- context 'with year option' do
166
- let(:options){ { :year => 2011 } }
167
-
168
- context 'month abbr String' do
169
- let(:input){ 'Dec' }
170
- it { should eq Time.zone.parse('2011-12-01 00:00:00') }
171
- end
172
-
173
- context 'Fixnum 12' do
174
- let(:input){ 10 }
175
- it { should eq Time.zone.parse('2011-10-01 00:00:00') }
176
- end
177
- end
178
- end
179
-
180
- describe '#quarter' do
181
- subject { ByStar::Normalization.quarter(input, options) }
182
- it_behaves_like 'time normalization from string'
183
- it_behaves_like 'time normalization from date/time'
184
-
185
- context 'Fixnum 1' do
186
- let(:input){ 1 }
187
- it { should eq Time.zone.parse('2014-01-01 00:00:00') }
188
- end
189
-
190
- context 'Fixnum 2' do
191
- let(:input){ 2 }
192
- it { should eq Time.zone.parse('2014-04-01 00:00:00') }
193
- end
194
-
195
- context 'Fixnum 3' do
196
- let(:input){ 3 }
197
- it { should eq Time.zone.parse('2014-07-01 00:00:00') }
198
- end
199
-
200
- context 'Fixnum 4' do
201
- let(:input){ 4 }
202
- it { should eq Time.zone.parse('2014-10-01 00:00:00') }
203
- end
204
-
205
- context 'with year option' do
206
- let(:options){ { :year => 2011 } }
207
-
208
- context 'Fixnum 3' do
209
- let(:input){ 3 }
210
- it { should eq Time.zone.parse('2011-07-01 00:00:00') }
211
- end
212
- end
213
-
214
- context 'out of range' do
215
- specify { ->{ ByStar::Normalization.quarter(0) }.should raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
216
- specify { ->{ ByStar::Normalization.quarter(5) }.should raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
217
- end
218
- end
219
-
220
- describe '#year' do
221
- subject { ByStar::Normalization.year(input, options) }
222
- it_behaves_like 'time normalization from string'
223
- it_behaves_like 'time normalization from date/time'
224
-
225
- context 'Fixnum 69' do
226
- let(:input){ 69 }
227
- it { should eq Time.zone.parse('2069-01-01 00:00:00') }
228
- end
229
-
230
- context 'Fixnum 99' do
231
- let(:input){ 99 }
232
- it { should eq Time.zone.parse('1999-01-01 00:00:00') }
233
- end
234
-
235
- context 'Fixnum 2001' do
236
- let(:input){ 1 }
237
- it { should eq Time.zone.parse('2001-01-01 00:00:00') }
238
- end
239
-
240
- context 'String 01' do
241
- let(:input){ '01' }
242
- it { should eq Time.zone.parse('2001-01-01 00:00:00') }
243
- end
244
-
245
- context 'String 70' do
246
- let(:input){ '70' }
247
- it { should eq Time.zone.parse('1970-01-01 00:00:00') }
248
- end
249
-
250
- context 'String 2001' do
251
- let(:input){ '2001' }
252
- it { should eq Time.zone.parse('2001-01-01 00:00:00') }
253
- end
254
- end
255
- end
1
+ require 'spec_helper'
2
+
3
+ describe ByStar::Normalization do
4
+
5
+ let(:options){ {} }
6
+
7
+ shared_examples_for 'time normalization from string' do
8
+
9
+ context 'when Chronic is defined' do
10
+
11
+ context 'date String' do
12
+ let(:input){ '2014-01-01' }
13
+ it { should eq Time.zone.parse('2014-01-01 12:00:00') }
14
+ end
15
+
16
+ context 'time String' do
17
+ let(:input){ '2014-01-01 15:00:00' }
18
+ it { should eq Time.zone.parse('2014-01-01 15:00:00') }
19
+ end
20
+
21
+ context 'natural language String' do
22
+ let(:input){ 'tomorrow at 3:30 pm' }
23
+ it { should eq Time.zone.parse('2014-01-02 15:30:00') }
24
+ end
25
+ end
26
+
27
+ context 'when Chronic is not defined' do
28
+
29
+ before { hide_const('Chronic') }
30
+
31
+ context 'date String' do
32
+ let(:input){ '2014-01-01' }
33
+ it { should eq Time.zone.parse('2014-01-01 00:00:00') }
34
+ end
35
+
36
+ context 'time String' do
37
+ let(:input){ '2014-01-01 15:00:00' }
38
+ it { should eq Time.zone.parse('2014-01-01 15:00:00') }
39
+ end
40
+
41
+ context 'natural language String' do
42
+ let(:input){ 'tomorrow at noon' }
43
+ it { expect{ subject }.to raise_error(ByStar::ParseError, "Cannot parse String #{input.inspect}") }
44
+ end
45
+ end
46
+ end
47
+
48
+ shared_examples_for 'time normalization from date/time' do
49
+ context 'Date' do
50
+ let(:input){ Date.parse('2014-01-01') }
51
+ it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
52
+ end
53
+
54
+ context 'DateTime' do
55
+ let(:input){ Time.zone.parse('2014-01-01 15:00:00').to_datetime }
56
+ it { expect eq Time.zone.parse('2014-01-01 15:00:00') }
57
+ end
58
+
59
+ context 'Time' do
60
+ let(:input){ Time.zone.parse('2014-01-01 15:00:00') }
61
+ it { expect eq Time.zone.parse('2014-01-01 15:00:00') }
62
+ end
63
+ end
64
+
65
+ describe '#time' do
66
+ subject { ByStar::Normalization.time(input) }
67
+ it_behaves_like 'time normalization from string'
68
+ it_behaves_like 'time normalization from date/time'
69
+ end
70
+
71
+ describe '#week' do
72
+ subject { ByStar::Normalization.week(input, options) }
73
+ it_behaves_like 'time normalization from string'
74
+ it_behaves_like 'time normalization from date/time'
75
+
76
+ context 'Integer -1' do
77
+ let(:input){ -1 }
78
+ it { expect{subject}.to raise_error(ByStar::ParseError, 'Week number must be between 0 and 52') }
79
+ end
80
+
81
+ context 'Integer 0' do
82
+ let(:input){ 0 }
83
+ it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
84
+ end
85
+
86
+ context 'Integer 20' do
87
+ let(:input){ 20 }
88
+ it { expect eq Time.zone.parse('2014-05-21 00:00:00') }
89
+ end
90
+
91
+ context 'Integer 53' do
92
+ let(:input){ 53 }
93
+ it { expect{subject}.to raise_error(ByStar::ParseError, 'Week number must be between 0 and 52') }
94
+ end
95
+
96
+ context 'with year option' do
97
+ let(:options){ { year: 2011 } }
98
+
99
+ context 'Integer 0' do
100
+ let(:input){ 0 }
101
+ it { expect eq Time.zone.parse('2011-01-01 00:00:00') }
102
+ end
103
+
104
+ context 'Integer 20' do
105
+ let(:input){ 20 }
106
+ it { expect eq Time.zone.parse('2011-05-21 00:00:00') }
107
+ end
108
+ end
109
+ end
110
+
111
+ describe '#cweek' do
112
+ subject { ByStar::Normalization.cweek(input, options) }
113
+ it_behaves_like 'time normalization from string'
114
+ it_behaves_like 'time normalization from date/time'
115
+
116
+ context 'Integer 9' do
117
+ let(:input){ 0 }
118
+ it { expect{subject}.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53') }
119
+ end
120
+
121
+ context 'Integer 1' do
122
+ let(:input){ 1 }
123
+ it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
124
+ end
125
+
126
+ context 'Integer 21' do
127
+ let(:input){ 21 }
128
+ it { expect eq Time.zone.parse('2014-05-21 00:00:00') }
129
+ end
130
+
131
+ context 'Integer 54' do
132
+ let(:input){ 54 }
133
+ it { expect{subject}.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53') }
134
+ end
135
+
136
+ context 'with year option' do
137
+ let(:options){ { year: 2011 } }
138
+
139
+ context 'Integer 1' do
140
+ let(:input){ 1 }
141
+ it { expect eq Time.zone.parse('2011-01-01 00:00:00') }
142
+ end
143
+
144
+ context 'Integer 21' do
145
+ let(:input){ 21 }
146
+ it { expect eq Time.zone.parse('2011-05-21 00:00:00') }
147
+ end
148
+ end
149
+ end
150
+
151
+ describe '#fortnight' do
152
+ subject { ByStar::Normalization.fortnight(input, options) }
153
+ it_behaves_like 'time normalization from string'
154
+ it_behaves_like 'time normalization from date/time'
155
+
156
+ context 'Integer 0' do
157
+ let(:input){ 0 }
158
+ it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
159
+ end
160
+
161
+ context 'Integer 26' do
162
+ let(:input){ 26 }
163
+ it { expect eq Time.zone.parse('2014-12-31 00:00:00') }
164
+ end
165
+
166
+ context 'out of range' do
167
+ specify { expect{ ByStar::Normalization.fortnight(-1) }.to raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
168
+ specify { expect{ ByStar::Normalization.fortnight(27) }.to raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
169
+ end
170
+
171
+ context 'with year option' do
172
+ let(:options){ { year: 2011 } }
173
+
174
+ context 'Integer 0' do
175
+ let(:input){ 0 }
176
+ it { expect eq Time.zone.parse('2011-01-01 00:00:00') }
177
+ end
178
+
179
+ context 'Integer 26' do
180
+ let(:input){ 26 }
181
+ it { expect eq Time.zone.parse('2011-12-31 00:00:00') }
182
+ end
183
+ end
184
+ end
185
+
186
+ describe '#month' do
187
+ subject { ByStar::Normalization.month(input, options) }
188
+ it_behaves_like 'time normalization from date/time'
189
+
190
+ context 'month abbr String' do
191
+ let(:input){ 'Feb' }
192
+ it { expect eq Time.zone.parse('2014-02-01 00:00:00') }
193
+ end
194
+
195
+ context 'month full String' do
196
+ let(:input){ 'February' }
197
+ it { expect eq Time.zone.parse('2014-02-01 00:00:00') }
198
+ end
199
+
200
+ context 'number String' do
201
+ let(:input){ '2' }
202
+ it { expect eq Time.zone.parse('2014-02-01 00:00:00') }
203
+ end
204
+
205
+ context 'Integer' do
206
+ let(:input){ 2 }
207
+ it { expect eq Time.zone.parse('2014-02-01 00:00:00') }
208
+ end
209
+
210
+ context 'out of range' do
211
+ specify { expect{ ByStar::Normalization.month(0) }.to raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
212
+ specify { expect{ ByStar::Normalization.month(13) }.to raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
213
+ end
214
+
215
+ context 'with year option' do
216
+ let(:options){ { year: 2011 } }
217
+
218
+ context 'month abbr String' do
219
+ let(:input){ 'Dec' }
220
+ it { expect eq Time.zone.parse('2011-12-01 00:00:00') }
221
+ end
222
+
223
+ context 'Integer 12' do
224
+ let(:input){ 10 }
225
+ it { expect eq Time.zone.parse('2011-10-01 00:00:00') }
226
+ end
227
+ end
228
+ end
229
+
230
+ describe '#quarter' do
231
+ subject { ByStar::Normalization.quarter(input, options) }
232
+ it_behaves_like 'time normalization from string'
233
+ it_behaves_like 'time normalization from date/time'
234
+
235
+ context 'Integer 1' do
236
+ let(:input){ 1 }
237
+ it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
238
+ end
239
+
240
+ context 'Integer 2' do
241
+ let(:input){ 2 }
242
+ it { expect eq Time.zone.parse('2014-04-01 00:00:00') }
243
+ end
244
+
245
+ context 'Integer 3' do
246
+ let(:input){ 3 }
247
+ it { expect eq Time.zone.parse('2014-07-01 00:00:00') }
248
+ end
249
+
250
+ context 'Integer 4' do
251
+ let(:input){ 4 }
252
+ it { expect eq Time.zone.parse('2014-10-01 00:00:00') }
253
+ end
254
+
255
+ context 'with year option' do
256
+ let(:options){ { year: 2011 } }
257
+
258
+ context 'Integer 3' do
259
+ let(:input){ 3 }
260
+ it { expect eq Time.zone.parse('2011-07-01 00:00:00') }
261
+ end
262
+ end
263
+
264
+ context 'out of range' do
265
+ specify { expect{ ByStar::Normalization.quarter(0) }.to raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
266
+ specify { expect{ ByStar::Normalization.quarter(5) }.to raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
267
+ end
268
+ end
269
+
270
+ describe '#year' do
271
+ subject { ByStar::Normalization.year(input, options) }
272
+ it_behaves_like 'time normalization from string'
273
+ it_behaves_like 'time normalization from date/time'
274
+
275
+ context 'Integer 69' do
276
+ let(:input){ 69 }
277
+ it { expect eq Time.zone.parse('2069-01-01 00:00:00') }
278
+ end
279
+
280
+ context 'Integer 99' do
281
+ let(:input){ 99 }
282
+ it { expect eq Time.zone.parse('1999-01-01 00:00:00') }
283
+ end
284
+
285
+ context 'Integer 2001' do
286
+ let(:input){ 1 }
287
+ it { expect eq Time.zone.parse('2001-01-01 00:00:00') }
288
+ end
289
+
290
+ context 'String 01' do
291
+ let(:input){ '01' }
292
+ it { expect eq Time.zone.parse('2001-01-01 00:00:00') }
293
+ end
294
+
295
+ context 'String 70' do
296
+ let(:input){ '70' }
297
+ it { expect eq Time.zone.parse('1970-01-01 00:00:00') }
298
+ end
299
+
300
+ context 'String 2001' do
301
+ let(:input){ '2001' }
302
+ it { expect eq Time.zone.parse('2001-01-01 00:00:00') }
303
+ end
304
+ end
305
+ end