|
173 | 173 | WorkingHours::Config.time_zone = 'Tokyo'
|
174 | 174 | expect(advance_to_working_time(Time.new(2014, 4, 7, 0, 0, 0)).zone).to eq('JST')
|
175 | 175 | end
|
| 176 | + |
| 177 | + it 'do not leak nanoseconds when advancing' do |
| 178 | + expect(advance_to_working_time(Time.utc(2014, 4, 7, 5, 0, 0, 123456.789))).to eq(Time.utc(2014, 4, 7, 9, 0, 0, 0)) |
| 179 | + end |
176 | 180 | end
|
177 | 181 |
|
178 | 182 | describe '#advance_to_closing_time' do
|
|
240 | 244 | end
|
241 | 245 |
|
242 | 246 | let(:monday_morning) { Time.utc(2014, 4, 7, 0) }
|
243 |
| - let(:monday_closing) { Time.utc(2014, 4, 7) + 86399.999999 } |
| 247 | + let(:monday_closing) { Time.utc(2014, 4, 7) + WorkingHours::Config::MIDNIGHT } |
244 | 248 | let(:tuesday_closing) { Time.utc(2014, 4, 8, 17) }
|
245 | 249 | let(:sunday) { Time.utc(2014, 4, 6, 17) }
|
246 | 250 |
|
|
255 | 259 | it 'moves over midnight' do
|
256 | 260 | expect(advance_to_closing_time(sunday)).to eq(monday_closing)
|
257 | 261 | end
|
| 262 | + |
| 263 | + it 'give precise computation with nothing other than miliseconds' do |
| 264 | + pending "iso8601 is not precise enough on AS < 4" if ActiveSupport::VERSION::MAJOR <= 4 |
| 265 | + expect(advance_to_closing_time(monday_morning).iso8601(25)).to eq("2014-04-07T23:59:59.9999990000000000000000000Z") |
| 266 | + end |
258 | 267 | end
|
259 | 268 |
|
260 | 269 | it 'works with any input timezone (converts to config)' do
|
|
271 | 280 | WorkingHours::Config.time_zone = 'Tokyo'
|
272 | 281 | expect(advance_to_closing_time(Time.new(2014, 4, 7, 0, 0, 0)).zone).to eq('JST')
|
273 | 282 | end
|
| 283 | + |
| 284 | + it 'do not leak nanoseconds when advancing' do |
| 285 | + expect(advance_to_closing_time(Time.utc(2014, 4, 7, 5, 0, 0, 123456.789))).to eq(Time.utc(2014, 4, 7, 17, 0, 0, 0)) |
| 286 | + end |
274 | 287 | end
|
275 | 288 |
|
276 | 289 | describe '#next_working_time' do
|
|
544 | 557 | )).to eq(7.hours)
|
545 | 558 | end
|
546 | 559 |
|
| 560 | + it 'uses precise computation to avoid useless loops' do |
| 561 | + # +200 usec on each time, using floating point would cause |
| 562 | + # precision issues and require several iterations |
| 563 | + expect(self).to receive(:advance_to_working_time).twice.and_call_original |
| 564 | + expect(working_time_between( |
| 565 | + Time.utc(2014, 4, 7, 5, 0, 0, 200), |
| 566 | + Time.utc(2014, 4, 7, 15, 0, 0, 200), |
| 567 | + )).to eq(6.hours) |
| 568 | + end |
| 569 | + |
| 570 | + it 'do not cause infinite loop if the time is not advancing properly' do |
| 571 | + # simulate some computation/precision error |
| 572 | + expect(self).to receive(:advance_to_working_time).twice do |time| |
| 573 | + time.change(hour: 9) - 0.0001 |
| 574 | + end |
| 575 | + expect { working_time_between( |
| 576 | + Time.utc(2014, 4, 7, 5, 0, 0), |
| 577 | + Time.utc(2014, 4, 7, 15, 0, 0), |
| 578 | + ) }.to raise_error(RuntimeError, /Invalid loop detected in working_time_between \(from=2014-04-07T08:59:59.999/) |
| 579 | + end |
| 580 | + |
547 | 581 | # generates two times with +0ms, +250ms, +500ms, +750ms and +1s
|
548 | 582 | # then for each combination compare the result with a ruby diff
|
549 | 583 | context 'with precise miliseconds timings' do
|
|
0 commit comments