by_star 3.0.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/mysql.yml +92 -0
  3. data/.github/workflows/postgresql.yml +99 -0
  4. data/.gitignore +6 -5
  5. data/.travis.yml +92 -61
  6. data/CHANGELOG.md +63 -44
  7. data/Gemfile +18 -18
  8. data/MIT-LICENSE +20 -20
  9. data/README.md +616 -577
  10. data/Rakefile +18 -18
  11. data/UPGRADING +4 -6
  12. data/by_star.gemspec +34 -34
  13. data/cleaner.rb +24 -24
  14. data/lib/by_star/base.rb +69 -68
  15. data/lib/by_star/between.rb +185 -156
  16. data/lib/by_star/directional.rb +35 -37
  17. data/lib/by_star/kernel/date.rb +41 -50
  18. data/lib/by_star/kernel/in_time_zone.rb +20 -0
  19. data/lib/by_star/kernel/time.rb +41 -41
  20. data/lib/by_star/normalization.rb +156 -127
  21. data/lib/by_star/orm/active_record/by_star.rb +75 -61
  22. data/lib/by_star/orm/mongoid/by_star.rb +90 -76
  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 -17
  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 -26
  31. data/spec/gemfiles/Gemfile.rails +5 -0
  32. data/spec/gemfiles/Gemfile.rails32 +7 -0
  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 -10
  37. data/spec/gemfiles/Gemfile.rails51 +7 -10
  38. data/spec/gemfiles/Gemfile.rails52 +7 -0
  39. data/spec/gemfiles/Gemfile.rails60 +7 -0
  40. data/spec/gemfiles/Gemfile.rails61 +7 -0
  41. data/spec/integration/active_record/active_record_spec.rb +41 -38
  42. data/spec/integration/mongoid/mongoid_spec.rb +39 -37
  43. data/spec/integration/shared/at_time.rb +53 -0
  44. data/spec/integration/shared/between_dates.rb +99 -0
  45. data/spec/integration/shared/between_times.rb +99 -82
  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 -96
  49. data/spec/integration/shared/by_direction.rb +126 -172
  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 -0
  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 -29
  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 -305
  64. data/tmp/.gitignore +1 -1
  65. metadata +33 -21
  66. data/spec/gemfiles/Gemfile.master +0 -6
  67. data/spec/integration/shared/scope_parameter.rb +0 -73
@@ -1,305 +1,384 @@
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
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