by_star 4.0.0 → 4.0.1

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/mysql.yml +92 -92
  3. data/.github/workflows/postgresql.yml +99 -99
  4. data/.gitignore +6 -6
  5. data/.travis.yml +92 -92
  6. data/CHANGELOG.md +63 -59
  7. data/Gemfile +18 -18
  8. data/MIT-LICENSE +20 -20
  9. data/README.md +616 -616
  10. data/Rakefile +18 -18
  11. data/UPGRADING +4 -4
  12. data/by_star.gemspec +34 -34
  13. data/cleaner.rb +24 -24
  14. data/lib/by_star/base.rb +69 -69
  15. data/lib/by_star/between.rb +185 -185
  16. data/lib/by_star/directional.rb +35 -35
  17. data/lib/by_star/kernel/date.rb +41 -41
  18. data/lib/by_star/kernel/in_time_zone.rb +20 -20
  19. data/lib/by_star/kernel/time.rb +41 -41
  20. data/lib/by_star/normalization.rb +156 -156
  21. data/lib/by_star/orm/active_record/by_star.rb +75 -75
  22. data/lib/by_star/orm/mongoid/by_star.rb +90 -90
  23. data/lib/by_star/orm/mongoid/reorder.rb +23 -23
  24. data/lib/by_star/version.rb +3 -3
  25. data/lib/by_star.rb +18 -18
  26. data/spec/database.yml +15 -15
  27. data/spec/fixtures/active_record/models.rb +12 -12
  28. data/spec/fixtures/active_record/schema.rb +19 -19
  29. data/spec/fixtures/mongoid/models.rb +31 -31
  30. data/spec/fixtures/shared/seeds.rb +36 -36
  31. data/spec/gemfiles/Gemfile.rails +5 -5
  32. data/spec/gemfiles/Gemfile.rails32 +7 -7
  33. data/spec/gemfiles/Gemfile.rails40 +7 -7
  34. data/spec/gemfiles/Gemfile.rails41 +7 -7
  35. data/spec/gemfiles/Gemfile.rails42 +7 -7
  36. data/spec/gemfiles/Gemfile.rails50 +7 -7
  37. data/spec/gemfiles/Gemfile.rails51 +7 -7
  38. data/spec/gemfiles/Gemfile.rails52 +7 -7
  39. data/spec/gemfiles/Gemfile.rails60 +7 -7
  40. data/spec/gemfiles/Gemfile.rails61 +7 -7
  41. data/spec/integration/active_record/active_record_spec.rb +41 -41
  42. data/spec/integration/mongoid/mongoid_spec.rb +39 -39
  43. data/spec/integration/shared/at_time.rb +53 -53
  44. data/spec/integration/shared/between_dates.rb +99 -99
  45. data/spec/integration/shared/between_times.rb +99 -99
  46. data/spec/integration/shared/by_calendar_month.rb +55 -55
  47. data/spec/integration/shared/by_cweek.rb +54 -54
  48. data/spec/integration/shared/by_day.rb +120 -120
  49. data/spec/integration/shared/by_direction.rb +126 -126
  50. data/spec/integration/shared/by_fortnight.rb +48 -48
  51. data/spec/integration/shared/by_month.rb +50 -50
  52. data/spec/integration/shared/by_quarter.rb +49 -49
  53. data/spec/integration/shared/by_week.rb +54 -54
  54. data/spec/integration/shared/by_weekend.rb +49 -49
  55. data/spec/integration/shared/by_year.rb +48 -48
  56. data/spec/integration/shared/index_scope_parameter.rb +111 -111
  57. data/spec/integration/shared/offset_parameter.rb +32 -32
  58. data/spec/integration/shared/order_parameter.rb +36 -36
  59. data/spec/integration/shared/relative.rb +174 -174
  60. data/spec/spec_helper.rb +33 -33
  61. data/spec/unit/kernel_date_spec.rb +113 -113
  62. data/spec/unit/kernel_time_spec.rb +57 -57
  63. data/spec/unit/normalization_spec.rb +384 -384
  64. data/tmp/.gitignore +1 -1
  65. metadata +3 -3
@@ -1,384 +1,384 @@
1
- require 'spec_helper'
2
-
3
- describe ByStar::Normalization do
4
-
5
- let(:options){ {} }
6
-
7
- shared_examples_for 'date 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 Date.parse('2014-01-01') }
14
- end
15
-
16
- context 'time String' do
17
- let(:input){ '2014-01-01 15:00:00' }
18
- it { should eq Date.parse('2014-01-01') }
19
- end
20
-
21
- context 'natural language String' do
22
- let(:input){ 'tomorrow at 3:30 pm' }
23
- it { should eq Date.parse('2014-01-02') }
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 Date.parse('2014-01-01') }
34
- end
35
-
36
- context 'time String' do
37
- let(:input){ '2014-01-01 15:00:00' }
38
- it { should eq Date.parse('2014-01-01') }
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 'date normalization from time value' do
49
- context 'Date' do
50
- let(:input){ Date.parse('2014-01-01') }
51
- it { expect eq Date.parse('2014-01-01') }
52
- end
53
-
54
- context 'DateTime' do
55
- let(:input){ Date.parse('2014-01-01').to_datetime }
56
- it { expect eq Date.parse('2014-01-01') }
57
- end
58
-
59
- context 'Time' do
60
- let(:input){ Date.parse('2014-01-01') }
61
- it { expect eq Date.parse('2014-01-01') }
62
- end
63
- end
64
-
65
- describe '#time' do
66
- subject { ByStar::Normalization.time(input) }
67
-
68
- context 'when Chronic is defined' do
69
-
70
- context 'date String' do
71
- let(:input){ '2014-01-01' }
72
- it { should eq Time.zone.parse('2014-01-01 12:00:00') }
73
- end
74
-
75
- context 'time String' do
76
- let(:input){ '2014-01-01 15:00:00' }
77
- it { should eq Time.zone.parse('2014-01-01 15:00:00') }
78
- end
79
-
80
- context 'natural language String' do
81
- let(:input){ 'tomorrow at 3:30 pm' }
82
- it { should eq Time.zone.parse('2014-01-02 15:30:00') }
83
- end
84
- end
85
-
86
- context 'when Chronic is not defined' do
87
-
88
- before { hide_const('Chronic') }
89
-
90
- context 'date String' do
91
- let(:input){ '2014-01-01' }
92
- it { should eq Time.zone.parse('2014-01-01 00:00:00') }
93
- end
94
-
95
- context 'time String' do
96
- let(:input){ '2014-01-01 15:00:00' }
97
- it { should eq Time.zone.parse('2014-01-01 15:00:00') }
98
- end
99
-
100
- context 'natural language String' do
101
- let(:input){ 'tomorrow at noon' }
102
- it { expect{ subject }.to raise_error(ByStar::ParseError, "Cannot parse String #{input.inspect}") }
103
- end
104
- end
105
-
106
- context 'Date' do
107
- let(:input){ Date.parse('2014-01-01') }
108
- it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
109
- end
110
-
111
- context 'DateTime' do
112
- let(:input){ Time.zone.parse('2014-01-01 15:00:00').to_datetime }
113
- it { expect eq Time.zone.parse('2014-01-01 15:00:00') }
114
- end
115
-
116
- context 'Time' do
117
- let(:input){ Time.zone.parse('2014-01-01 15:00:00') }
118
- it { expect eq Time.zone.parse('2014-01-01 15:00:00') }
119
- end
120
- end
121
-
122
- describe '#week' do
123
- subject { ByStar::Normalization.week(input, options) }
124
- it_behaves_like 'date normalization from string'
125
- it_behaves_like 'date normalization from time value'
126
-
127
- context 'Integer -1' do
128
- let(:input){ -1 }
129
- it { expect{subject}.to raise_error(ByStar::ParseError, 'Week number must be between 0 and 52') }
130
- end
131
-
132
- context 'Integer 0' do
133
- let(:input){ 0 }
134
- it { expect eq Date.parse('2014-01-01') }
135
- end
136
-
137
- context 'Integer 20' do
138
- let(:input){ 20 }
139
- it { expect eq Date.parse('2014-05-21') }
140
- end
141
-
142
- context 'Integer 53' do
143
- let(:input){ 53 }
144
- it { expect{subject}.to raise_error(ByStar::ParseError, 'Week number must be between 0 and 52') }
145
- end
146
-
147
- context 'with year option' do
148
- let(:options){ { year: 2011 } }
149
-
150
- context 'Integer 0' do
151
- let(:input){ 0 }
152
- it { expect eq Date.parse('2011-01-01') }
153
- end
154
-
155
- context 'Integer 20' do
156
- let(:input){ 20 }
157
- it { expect eq Date.parse('2011-05-21') }
158
- end
159
- end
160
- end
161
-
162
- describe '#cweek' do
163
- subject { ByStar::Normalization.cweek(input, options) }
164
- it_behaves_like 'date normalization from string'
165
- it_behaves_like 'date normalization from time value'
166
-
167
- context 'Integer 9' do
168
- let(:input){ 0 }
169
- it { expect{subject}.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53') }
170
- end
171
-
172
- context 'Integer 1' do
173
- let(:input){ 1 }
174
- it { expect eq Date.parse('2014-01-01') }
175
- end
176
-
177
- context 'Integer 21' do
178
- let(:input){ 21 }
179
- it { expect eq Date.parse('2014-05-21') }
180
- end
181
-
182
- context 'Integer 54' do
183
- let(:input){ 54 }
184
- it { expect{subject}.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53') }
185
- end
186
-
187
- context 'with year option' do
188
- let(:options){ { year: 2011 } }
189
-
190
- context 'Integer 1' do
191
- let(:input){ 1 }
192
- it { expect eq Date.parse('2011-01-01') }
193
- end
194
-
195
- context 'Integer 21' do
196
- let(:input){ 21 }
197
- it { expect eq Date.parse('2011-05-21') }
198
- end
199
- end
200
- end
201
-
202
- describe '#fortnight' do
203
- subject { ByStar::Normalization.fortnight(input, options) }
204
- it_behaves_like 'date normalization from string'
205
- it_behaves_like 'date normalization from time value'
206
-
207
- context 'Integer 0' do
208
- let(:input){ 0 }
209
- it { expect eq Date.parse('2014-01-01') }
210
- end
211
-
212
- context 'Integer 26' do
213
- let(:input){ 26 }
214
- it { expect eq Date.parse('2014-12-31') }
215
- end
216
-
217
- context 'out of range' do
218
- specify { expect{ ByStar::Normalization.fortnight(-1) }.to raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
219
- specify { expect{ ByStar::Normalization.fortnight(27) }.to raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
220
- end
221
-
222
- context 'with year option' do
223
- let(:options){ { year: 2011 } }
224
-
225
- context 'Integer 0' do
226
- let(:input){ 0 }
227
- it { expect eq Date.parse('2011-01-01') }
228
- end
229
-
230
- context 'Integer 26' do
231
- let(:input){ 26 }
232
- it { expect eq Date.parse('2011-12-31') }
233
- end
234
- end
235
- end
236
-
237
- describe '#month' do
238
- subject { ByStar::Normalization.month(input, options) }
239
- it_behaves_like 'date normalization from time value'
240
-
241
- context 'month abbr String' do
242
- let(:input){ 'Feb' }
243
- it { expect eq Date.parse('2014-02-01') }
244
- end
245
-
246
- context 'month full String' do
247
- let(:input){ 'February' }
248
- it { expect eq Date.parse('2014-02-01') }
249
- end
250
-
251
- context 'number String' do
252
- let(:input){ '2' }
253
- it { expect eq Date.parse('2014-02-01') }
254
- end
255
-
256
- context 'Integer' do
257
- let(:input){ 2 }
258
- it { expect eq Date.parse('2014-02-01') }
259
- end
260
-
261
- context 'out of range' do
262
- specify { expect{ ByStar::Normalization.month(0) }.to raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
263
- specify { expect{ ByStar::Normalization.month(13) }.to raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
264
- end
265
-
266
- context 'with year option' do
267
- let(:options){ { year: 2011 } }
268
-
269
- context 'month abbr String' do
270
- let(:input){ 'Dec' }
271
- it { expect eq Date.parse('2011-12-01') }
272
- end
273
-
274
- context 'Integer 12' do
275
- let(:input){ 10 }
276
- it { expect eq Date.parse('2011-10-01') }
277
- end
278
- end
279
- end
280
-
281
- describe '#quarter' do
282
- subject { ByStar::Normalization.quarter(input, options) }
283
- it_behaves_like 'date normalization from string'
284
- it_behaves_like 'date normalization from time value'
285
-
286
- context 'Integer 1' do
287
- let(:input){ 1 }
288
- it { expect eq Date.parse('2014-01-01') }
289
- end
290
-
291
- context 'Integer 2' do
292
- let(:input){ 2 }
293
- it { expect eq Date.parse('2014-04-01') }
294
- end
295
-
296
- context 'Integer 3' do
297
- let(:input){ 3 }
298
- it { expect eq Date.parse('2014-07-01') }
299
- end
300
-
301
- context 'Integer 4' do
302
- let(:input){ 4 }
303
- it { expect eq Date.parse('2014-10-01') }
304
- end
305
-
306
- context 'with year option' do
307
- let(:options){ { year: 2011 } }
308
-
309
- context 'Integer 3' do
310
- let(:input){ 3 }
311
- it { expect eq Date.parse('2011-07-01') }
312
- end
313
- end
314
-
315
- context 'out of range' do
316
- specify { expect{ ByStar::Normalization.quarter(0) }.to raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
317
- specify { expect{ ByStar::Normalization.quarter(5) }.to raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
318
- end
319
- end
320
-
321
- describe '#year' do
322
- subject { ByStar::Normalization.year(input, options) }
323
- it_behaves_like 'date normalization from string'
324
- it_behaves_like 'date normalization from time value'
325
-
326
- context 'Integer 69' do
327
- let(:input){ 69 }
328
- it { expect eq Date.parse('2069-01-01') }
329
- end
330
-
331
- context 'Integer 99' do
332
- let(:input){ 99 }
333
- it { expect eq Date.parse('1999-01-01') }
334
- end
335
-
336
- context 'Integer 2001' do
337
- let(:input){ 1 }
338
- it { expect eq Date.parse('2001-01-01') }
339
- end
340
-
341
- context 'String 01' do
342
- let(:input){ '01' }
343
- it { expect eq Date.parse('2001-01-01') }
344
- end
345
-
346
- context 'String 70' do
347
- let(:input){ '70' }
348
- it { expect eq Date.parse('1970-01-01') }
349
- end
350
-
351
- context 'String 2001' do
352
- let(:input){ '2001' }
353
- it { expect eq Date.parse('2001-01-01') }
354
- end
355
- end
356
-
357
- describe '#time_in_units' do
358
- subject { ByStar::Normalization.time_in_units(input) }
359
-
360
- context 'when less than a day' do
361
- let(:input) { 34876 }
362
- it { is_expected.to eq(days: 0, hour: 9, min: 41, sec: 16) }
363
- end
364
-
365
- context 'when more than a day' do
366
- let(:input) { 97532 }
367
- it { is_expected.to eq(days: 1, hour: 3, min: 5, sec: 32) }
368
- end
369
- end
370
-
371
- describe '#apply_offset_start' do
372
- subject { ByStar::Normalization.apply_offset_start(input, offset) }
373
- let(:input) { Time.zone.parse('2020-04-05 00:00:00') }
374
- let(:offset) { 5.hours }
375
- it { is_expected.to eq Time.zone.parse('2020-04-05 05:00:00') }
376
- end
377
-
378
- describe '#apply_offset_end' do
379
- subject { ByStar::Normalization.apply_offset_end(input, offset) }
380
- let(:input) { Time.zone.parse('2020-10-04 00:00:00') }
381
- let(:offset) { 5.hours }
382
- it { is_expected.to eq Time.zone.parse('2020-10-05 04:59:59') }
383
- end
384
- end
1
+ require 'spec_helper'
2
+
3
+ describe ByStar::Normalization do
4
+
5
+ let(:options){ {} }
6
+
7
+ shared_examples_for 'date 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 Date.parse('2014-01-01') }
14
+ end
15
+
16
+ context 'time String' do
17
+ let(:input){ '2014-01-01 15:00:00' }
18
+ it { should eq Date.parse('2014-01-01') }
19
+ end
20
+
21
+ context 'natural language String' do
22
+ let(:input){ 'tomorrow at 3:30 pm' }
23
+ it { should eq Date.parse('2014-01-02') }
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 Date.parse('2014-01-01') }
34
+ end
35
+
36
+ context 'time String' do
37
+ let(:input){ '2014-01-01 15:00:00' }
38
+ it { should eq Date.parse('2014-01-01') }
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 'date normalization from time value' do
49
+ context 'Date' do
50
+ let(:input){ Date.parse('2014-01-01') }
51
+ it { expect eq Date.parse('2014-01-01') }
52
+ end
53
+
54
+ context 'DateTime' do
55
+ let(:input){ Date.parse('2014-01-01').to_datetime }
56
+ it { expect eq Date.parse('2014-01-01') }
57
+ end
58
+
59
+ context 'Time' do
60
+ let(:input){ Date.parse('2014-01-01') }
61
+ it { expect eq Date.parse('2014-01-01') }
62
+ end
63
+ end
64
+
65
+ describe '#time' do
66
+ subject { ByStar::Normalization.time(input) }
67
+
68
+ context 'when Chronic is defined' do
69
+
70
+ context 'date String' do
71
+ let(:input){ '2014-01-01' }
72
+ it { should eq Time.zone.parse('2014-01-01 12:00:00') }
73
+ end
74
+
75
+ context 'time String' do
76
+ let(:input){ '2014-01-01 15:00:00' }
77
+ it { should eq Time.zone.parse('2014-01-01 15:00:00') }
78
+ end
79
+
80
+ context 'natural language String' do
81
+ let(:input){ 'tomorrow at 3:30 pm' }
82
+ it { should eq Time.zone.parse('2014-01-02 15:30:00') }
83
+ end
84
+ end
85
+
86
+ context 'when Chronic is not defined' do
87
+
88
+ before { hide_const('Chronic') }
89
+
90
+ context 'date String' do
91
+ let(:input){ '2014-01-01' }
92
+ it { should eq Time.zone.parse('2014-01-01 00:00:00') }
93
+ end
94
+
95
+ context 'time String' do
96
+ let(:input){ '2014-01-01 15:00:00' }
97
+ it { should eq Time.zone.parse('2014-01-01 15:00:00') }
98
+ end
99
+
100
+ context 'natural language String' do
101
+ let(:input){ 'tomorrow at noon' }
102
+ it { expect{ subject }.to raise_error(ByStar::ParseError, "Cannot parse String #{input.inspect}") }
103
+ end
104
+ end
105
+
106
+ context 'Date' do
107
+ let(:input){ Date.parse('2014-01-01') }
108
+ it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
109
+ end
110
+
111
+ context 'DateTime' do
112
+ let(:input){ Time.zone.parse('2014-01-01 15:00:00').to_datetime }
113
+ it { expect eq Time.zone.parse('2014-01-01 15:00:00') }
114
+ end
115
+
116
+ context 'Time' do
117
+ let(:input){ Time.zone.parse('2014-01-01 15:00:00') }
118
+ it { expect eq Time.zone.parse('2014-01-01 15:00:00') }
119
+ end
120
+ end
121
+
122
+ describe '#week' do
123
+ subject { ByStar::Normalization.week(input, options) }
124
+ it_behaves_like 'date normalization from string'
125
+ it_behaves_like 'date normalization from time value'
126
+
127
+ context 'Integer -1' do
128
+ let(:input){ -1 }
129
+ it { expect{subject}.to raise_error(ByStar::ParseError, 'Week number must be between 0 and 52') }
130
+ end
131
+
132
+ context 'Integer 0' do
133
+ let(:input){ 0 }
134
+ it { expect eq Date.parse('2014-01-01') }
135
+ end
136
+
137
+ context 'Integer 20' do
138
+ let(:input){ 20 }
139
+ it { expect eq Date.parse('2014-05-21') }
140
+ end
141
+
142
+ context 'Integer 53' do
143
+ let(:input){ 53 }
144
+ it { expect{subject}.to raise_error(ByStar::ParseError, 'Week number must be between 0 and 52') }
145
+ end
146
+
147
+ context 'with year option' do
148
+ let(:options){ { year: 2011 } }
149
+
150
+ context 'Integer 0' do
151
+ let(:input){ 0 }
152
+ it { expect eq Date.parse('2011-01-01') }
153
+ end
154
+
155
+ context 'Integer 20' do
156
+ let(:input){ 20 }
157
+ it { expect eq Date.parse('2011-05-21') }
158
+ end
159
+ end
160
+ end
161
+
162
+ describe '#cweek' do
163
+ subject { ByStar::Normalization.cweek(input, options) }
164
+ it_behaves_like 'date normalization from string'
165
+ it_behaves_like 'date normalization from time value'
166
+
167
+ context 'Integer 9' do
168
+ let(:input){ 0 }
169
+ it { expect{subject}.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53') }
170
+ end
171
+
172
+ context 'Integer 1' do
173
+ let(:input){ 1 }
174
+ it { expect eq Date.parse('2014-01-01') }
175
+ end
176
+
177
+ context 'Integer 21' do
178
+ let(:input){ 21 }
179
+ it { expect eq Date.parse('2014-05-21') }
180
+ end
181
+
182
+ context 'Integer 54' do
183
+ let(:input){ 54 }
184
+ it { expect{subject}.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53') }
185
+ end
186
+
187
+ context 'with year option' do
188
+ let(:options){ { year: 2011 } }
189
+
190
+ context 'Integer 1' do
191
+ let(:input){ 1 }
192
+ it { expect eq Date.parse('2011-01-01') }
193
+ end
194
+
195
+ context 'Integer 21' do
196
+ let(:input){ 21 }
197
+ it { expect eq Date.parse('2011-05-21') }
198
+ end
199
+ end
200
+ end
201
+
202
+ describe '#fortnight' do
203
+ subject { ByStar::Normalization.fortnight(input, options) }
204
+ it_behaves_like 'date normalization from string'
205
+ it_behaves_like 'date normalization from time value'
206
+
207
+ context 'Integer 0' do
208
+ let(:input){ 0 }
209
+ it { expect eq Date.parse('2014-01-01') }
210
+ end
211
+
212
+ context 'Integer 26' do
213
+ let(:input){ 26 }
214
+ it { expect eq Date.parse('2014-12-31') }
215
+ end
216
+
217
+ context 'out of range' do
218
+ specify { expect{ ByStar::Normalization.fortnight(-1) }.to raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
219
+ specify { expect{ ByStar::Normalization.fortnight(27) }.to raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
220
+ end
221
+
222
+ context 'with year option' do
223
+ let(:options){ { year: 2011 } }
224
+
225
+ context 'Integer 0' do
226
+ let(:input){ 0 }
227
+ it { expect eq Date.parse('2011-01-01') }
228
+ end
229
+
230
+ context 'Integer 26' do
231
+ let(:input){ 26 }
232
+ it { expect eq Date.parse('2011-12-31') }
233
+ end
234
+ end
235
+ end
236
+
237
+ describe '#month' do
238
+ subject { ByStar::Normalization.month(input, options) }
239
+ it_behaves_like 'date normalization from time value'
240
+
241
+ context 'month abbr String' do
242
+ let(:input){ 'Feb' }
243
+ it { expect eq Date.parse('2014-02-01') }
244
+ end
245
+
246
+ context 'month full String' do
247
+ let(:input){ 'February' }
248
+ it { expect eq Date.parse('2014-02-01') }
249
+ end
250
+
251
+ context 'number String' do
252
+ let(:input){ '2' }
253
+ it { expect eq Date.parse('2014-02-01') }
254
+ end
255
+
256
+ context 'Integer' do
257
+ let(:input){ 2 }
258
+ it { expect eq Date.parse('2014-02-01') }
259
+ end
260
+
261
+ context 'out of range' do
262
+ specify { expect{ ByStar::Normalization.month(0) }.to raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
263
+ specify { expect{ ByStar::Normalization.month(13) }.to raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
264
+ end
265
+
266
+ context 'with year option' do
267
+ let(:options){ { year: 2011 } }
268
+
269
+ context 'month abbr String' do
270
+ let(:input){ 'Dec' }
271
+ it { expect eq Date.parse('2011-12-01') }
272
+ end
273
+
274
+ context 'Integer 12' do
275
+ let(:input){ 10 }
276
+ it { expect eq Date.parse('2011-10-01') }
277
+ end
278
+ end
279
+ end
280
+
281
+ describe '#quarter' do
282
+ subject { ByStar::Normalization.quarter(input, options) }
283
+ it_behaves_like 'date normalization from string'
284
+ it_behaves_like 'date normalization from time value'
285
+
286
+ context 'Integer 1' do
287
+ let(:input){ 1 }
288
+ it { expect eq Date.parse('2014-01-01') }
289
+ end
290
+
291
+ context 'Integer 2' do
292
+ let(:input){ 2 }
293
+ it { expect eq Date.parse('2014-04-01') }
294
+ end
295
+
296
+ context 'Integer 3' do
297
+ let(:input){ 3 }
298
+ it { expect eq Date.parse('2014-07-01') }
299
+ end
300
+
301
+ context 'Integer 4' do
302
+ let(:input){ 4 }
303
+ it { expect eq Date.parse('2014-10-01') }
304
+ end
305
+
306
+ context 'with year option' do
307
+ let(:options){ { year: 2011 } }
308
+
309
+ context 'Integer 3' do
310
+ let(:input){ 3 }
311
+ it { expect eq Date.parse('2011-07-01') }
312
+ end
313
+ end
314
+
315
+ context 'out of range' do
316
+ specify { expect{ ByStar::Normalization.quarter(0) }.to raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
317
+ specify { expect{ ByStar::Normalization.quarter(5) }.to raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
318
+ end
319
+ end
320
+
321
+ describe '#year' do
322
+ subject { ByStar::Normalization.year(input, options) }
323
+ it_behaves_like 'date normalization from string'
324
+ it_behaves_like 'date normalization from time value'
325
+
326
+ context 'Integer 69' do
327
+ let(:input){ 69 }
328
+ it { expect eq Date.parse('2069-01-01') }
329
+ end
330
+
331
+ context 'Integer 99' do
332
+ let(:input){ 99 }
333
+ it { expect eq Date.parse('1999-01-01') }
334
+ end
335
+
336
+ context 'Integer 2001' do
337
+ let(:input){ 1 }
338
+ it { expect eq Date.parse('2001-01-01') }
339
+ end
340
+
341
+ context 'String 01' do
342
+ let(:input){ '01' }
343
+ it { expect eq Date.parse('2001-01-01') }
344
+ end
345
+
346
+ context 'String 70' do
347
+ let(:input){ '70' }
348
+ it { expect eq Date.parse('1970-01-01') }
349
+ end
350
+
351
+ context 'String 2001' do
352
+ let(:input){ '2001' }
353
+ it { expect eq Date.parse('2001-01-01') }
354
+ end
355
+ end
356
+
357
+ describe '#time_in_units' do
358
+ subject { ByStar::Normalization.time_in_units(input) }
359
+
360
+ context 'when less than a day' do
361
+ let(:input) { 34876 }
362
+ it { is_expected.to eq(days: 0, hour: 9, min: 41, sec: 16) }
363
+ end
364
+
365
+ context 'when more than a day' do
366
+ let(:input) { 97532 }
367
+ it { is_expected.to eq(days: 1, hour: 3, min: 5, sec: 32) }
368
+ end
369
+ end
370
+
371
+ describe '#apply_offset_start' do
372
+ subject { ByStar::Normalization.apply_offset_start(input, offset) }
373
+ let(:input) { Time.zone.parse('2020-04-05 00:00:00') }
374
+ let(:offset) { 5.hours }
375
+ it { is_expected.to eq Time.zone.parse('2020-04-05 05:00:00') }
376
+ end
377
+
378
+ describe '#apply_offset_end' do
379
+ subject { ByStar::Normalization.apply_offset_end(input, offset) }
380
+ let(:input) { Time.zone.parse('2020-10-04 00:00:00') }
381
+ let(:offset) { 5.hours }
382
+ it { is_expected.to eq Time.zone.parse('2020-10-05 04:59:59') }
383
+ end
384
+ end