diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f7e7d0..59aba22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ # v1.3.0 * Improve supports for fractional seconds in input times by only rounding results at the end - [#42](https://github.com/Intrepidd/working_hours/issues/42) [#43](https://github.com/Intrepidd/working_hours/pull/43) +* Increase code safety by always initializing an empty hash for each day of the week in the precompiled config (inspired by [#35](https://github.com/Intrepidd/working_hours/pull/35) # v1.2.0 * Drop support for ruby 2.0, 2.1, 2.2 and 2.3 diff --git a/lib/working_hours/computation.rb b/lib/working_hours/computation.rb index 07fb60e..bc71e43 100644 --- a/lib/working_hours/computation.rb +++ b/lib/working_hours/computation.rb @@ -80,7 +80,7 @@ def advance_to_working_time time, config: nil end # find first working range after time time_in_day = time.seconds_since_midnight - (config[:working_hours][time.wday] || {}).each do |from, to| + config[:working_hours][time.wday].each do |from, to| return time if time_in_day >= from and time_in_day < to return time + (from - time_in_day) if from >= time_in_day end @@ -100,7 +100,7 @@ def advance_to_closing_time time, config: nil # find next working range after time time_in_day = time.seconds_since_midnight time = time.beginning_of_day - (config[:working_hours][time.wday] || {}).each do |from, to| + config[:working_hours][time.wday].each do |from, to| return time + to if time_in_day >= from and time_in_day < to return time + to if from >= time_in_day end @@ -131,7 +131,7 @@ def return_to_exact_working_time time, config: nil end # find last working range before time time_in_day = time.seconds_since_midnight - (config[:working_hours][time.wday] || {}).reverse_each do |from, to| + config[:working_hours][time.wday].reverse_each do |from, to| # round is used to suppress miliseconds hack from `end_of_day` return time if time_in_day > from and time_in_day <= to return (time - (time_in_day - to)) if to <= time_in_day diff --git a/lib/working_hours/config.rb b/lib/working_hours/config.rb index 462e378..81dea66 100644 --- a/lib/working_hours/config.rb +++ b/lib/working_hours/config.rb @@ -44,9 +44,8 @@ def precompiled validate_working_hours! config[:working_hours] validate_holidays! config[:holidays] validate_time_zone! config[:time_zone] - compiled = {working_hours: []} + compiled = { working_hours: Array.new(7) { Hash.new } } working_hours.each do |day, hours| - compiled[:working_hours][DAYS_OF_WEEK.index(day)] = {} hours.each do |start, finish| compiled[:working_hours][DAYS_OF_WEEK.index(day)][compile_time(start)] = compile_time(finish) end diff --git a/spec/working_hours/config_spec.rb b/spec/working_hours/config_spec.rb index e2ba767..79a0c62 100644 --- a/spec/working_hours/config_spec.rb +++ b/spec/working_hours/config_spec.rb @@ -266,16 +266,23 @@ it 'computes an optimized version' do expect(subject).to eq({ - :working_hours => [nil, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}], + :working_hours => [{}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {}], :holidays => Set.new([]), :time_zone => ActiveSupport::TimeZone['UTC'] }) end + it 'includes default values for each days so computation does not fail' do + WorkingHours::Config.working_hours = {:mon => {'08:00' => '14:00'}} + expect(subject[:working_hours]).to eq([{}, {28800=>50400}, {}, {}, {}, {}, {}]) + expect(WorkingHours.working_time_between(Time.utc(2014, 4, 14, 0), Time.utc(2014, 4, 21, 0))).to eq(3600*6) + expect(WorkingHours.add_seconds(Time.utc(2014, 4, 14, 0), 3600*7)).to eq(Time.utc(2014, 4, 21, 9)) + end + it 'supports seconds' do WorkingHours::Config.working_hours = {:mon => {'20:32:59' => '22:59:59'}} expect(subject).to eq({ - :working_hours => [nil, {73979 => 82799}], + :working_hours => [{}, {73979 => 82799}, {}, {}, {}, {}, {}], :holidays => Set.new([]), :time_zone => ActiveSupport::TimeZone['UTC'] }) @@ -284,7 +291,7 @@ it 'supports 24:00 (converts to 23:59:59.999999)' do WorkingHours::Config.working_hours = {:mon => {'20:00' => '24:00'}} expect(subject).to eq({ - :working_hours => [nil, {72000 => 86399.999999}], + :working_hours => [{}, {72000 => 86399.999999}, {}, {}, {}, {}, {}], :holidays => Set.new([]), :time_zone => ActiveSupport::TimeZone['UTC'] }) @@ -296,9 +303,9 @@ }.to change { WorkingHours::Config.precompiled[:working_hours] }.from( - [nil, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}] + [{}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {}] ).to( - [nil, {28800=>50400}] + [{}, {28800=>50400}, {}, {}, {}, {}, {}] ) end