working_hours 1.2.0 → 1.3.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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -1
- data/CHANGELOG.md +5 -1
- data/README.md +2 -2
- data/lib/working_hours/computation.rb +8 -8
- data/lib/working_hours/config.rb +1 -2
- data/lib/working_hours/version.rb +1 -1
- data/spec/working_hours/computation_spec.rb +22 -0
- data/spec/working_hours/config_spec.rb +12 -5
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4bdb747e39a652368403adb9ad97f3776a8d8ab28f841d70912bcab6141118ea
|
|
4
|
+
data.tar.gz: 74e1447b590b829f95e52fe3c5bac18e7a690dcc8b21683402982f5810b94d8c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee953af27c8d6622d8089feec9cd5b966613baff8239c11e488668ad07a48023efbd98d28599f9723c913b7e295ced2ac2b4cb5ef70711c4950ed8afea2aa107
|
|
7
|
+
data.tar.gz: 5b632e842d20ff83173c83a3e34c4bf166237f3689ba130db2cfd3031e027078f1efa1acbddac588198d78b07f3775c94e88f6d83fba328a9400629e92fab107
|
data/.travis.yml
CHANGED
|
@@ -4,7 +4,8 @@ rvm:
|
|
|
4
4
|
- 2.5.7
|
|
5
5
|
- 2.6.5
|
|
6
6
|
- 2.7.0
|
|
7
|
-
-
|
|
7
|
+
- 3.0.0
|
|
8
|
+
- jruby-9.2.14.0
|
|
8
9
|
gemfile:
|
|
9
10
|
- gemfiles/Gemfile.activesupport-4.x
|
|
10
11
|
- gemfiles/Gemfile.activesupport-5.x
|
|
@@ -15,6 +16,8 @@ jobs:
|
|
|
15
16
|
gemfile: gemfiles/Gemfile.activesupport-6.x
|
|
16
17
|
- rvm: 2.7.0
|
|
17
18
|
gemfile: gemfiles/Gemfile.activesupport-4.x
|
|
19
|
+
- rvm: 3.0.0
|
|
20
|
+
gemfile: gemfiles/Gemfile.activesupport-4.x
|
|
18
21
|
include:
|
|
19
22
|
- rvm: ruby-head
|
|
20
23
|
gemfile: gemfiles/Gemfile.activesupport-edge
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# Unreleased
|
|
2
2
|
|
|
3
|
-
[Compare master with v1.
|
|
3
|
+
[Compare master with v1.3.0](https://github.com/intrepidd/working_hours/compare/v1.3.0...master)
|
|
4
|
+
|
|
5
|
+
# v1.3.0
|
|
6
|
+
* 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)
|
|
7
|
+
* 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)
|
|
4
8
|
|
|
5
9
|
# v1.2.0
|
|
6
10
|
* Drop support for ruby 2.0, 2.1, 2.2 and 2.3
|
data/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# WorkingHours
|
|
2
2
|
|
|
3
|
-
[](https://travis-ci.com/Intrepidd/working_hours)
|
|
4
4
|
|
|
5
5
|
A modern ruby gem allowing to do time calculation with working hours.
|
|
6
6
|
|
|
7
7
|
Compatible and tested with:
|
|
8
|
-
- Ruby `2.4`, `2.5`, `2.6`, `2.7`, JRuby `9.2`
|
|
8
|
+
- Ruby `2.4`, `2.5`, `2.6`, `2.7`, `3.0`, JRuby `9.2`
|
|
9
9
|
- ActiveSupport `4.x`, `5.x`, `6.x`
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
@@ -34,7 +34,7 @@ module WorkingHours
|
|
|
34
34
|
|
|
35
35
|
def add_seconds origin, seconds, config: nil
|
|
36
36
|
config ||= wh_config
|
|
37
|
-
time = in_config_zone(origin, config: config)
|
|
37
|
+
time = in_config_zone(origin, config: config)
|
|
38
38
|
while seconds > 0
|
|
39
39
|
# roll to next business period
|
|
40
40
|
time = advance_to_working_time(time, config: config)
|
|
@@ -72,7 +72,7 @@ module WorkingHours
|
|
|
72
72
|
|
|
73
73
|
def advance_to_working_time time, config: nil
|
|
74
74
|
config ||= wh_config
|
|
75
|
-
time = in_config_zone(time, config: config)
|
|
75
|
+
time = in_config_zone(time, config: config)
|
|
76
76
|
loop do
|
|
77
77
|
# skip holidays and weekends
|
|
78
78
|
while not working_day?(time, config: config)
|
|
@@ -80,7 +80,7 @@ module WorkingHours
|
|
|
80
80
|
end
|
|
81
81
|
# find first working range after time
|
|
82
82
|
time_in_day = time.seconds_since_midnight
|
|
83
|
-
|
|
83
|
+
config[:working_hours][time.wday].each do |from, to|
|
|
84
84
|
return time if time_in_day >= from and time_in_day < to
|
|
85
85
|
return time + (from - time_in_day) if from >= time_in_day
|
|
86
86
|
end
|
|
@@ -91,7 +91,7 @@ module WorkingHours
|
|
|
91
91
|
|
|
92
92
|
def advance_to_closing_time time, config: nil
|
|
93
93
|
config ||= wh_config
|
|
94
|
-
time = in_config_zone(time, config: config)
|
|
94
|
+
time = in_config_zone(time, config: config)
|
|
95
95
|
loop do
|
|
96
96
|
# skip holidays and weekends
|
|
97
97
|
while not working_day?(time, config: config)
|
|
@@ -100,7 +100,7 @@ module WorkingHours
|
|
|
100
100
|
# find next working range after time
|
|
101
101
|
time_in_day = time.seconds_since_midnight
|
|
102
102
|
time = time.beginning_of_day
|
|
103
|
-
|
|
103
|
+
config[:working_hours][time.wday].each do |from, to|
|
|
104
104
|
return time + to if time_in_day >= from and time_in_day < to
|
|
105
105
|
return time + to if from >= time_in_day
|
|
106
106
|
end
|
|
@@ -123,7 +123,7 @@ module WorkingHours
|
|
|
123
123
|
|
|
124
124
|
def return_to_exact_working_time time, config: nil
|
|
125
125
|
config ||= wh_config
|
|
126
|
-
time = in_config_zone(time, config: config)
|
|
126
|
+
time = in_config_zone(time, config: config)
|
|
127
127
|
loop do
|
|
128
128
|
# skip holidays and weekends
|
|
129
129
|
while not working_day?(time, config: config)
|
|
@@ -131,7 +131,7 @@ module WorkingHours
|
|
|
131
131
|
end
|
|
132
132
|
# find last working range before time
|
|
133
133
|
time_in_day = time.seconds_since_midnight
|
|
134
|
-
|
|
134
|
+
config[:working_hours][time.wday].reverse_each do |from, to|
|
|
135
135
|
# round is used to suppress miliseconds hack from `end_of_day`
|
|
136
136
|
return time if time_in_day > from and time_in_day <= to
|
|
137
137
|
return (time - (time_in_day - to)) if to <= time_in_day
|
|
@@ -180,7 +180,7 @@ module WorkingHours
|
|
|
180
180
|
-working_time_between(to, from, config: config)
|
|
181
181
|
else
|
|
182
182
|
from = advance_to_working_time(in_config_zone(from, config: config))
|
|
183
|
-
to = in_config_zone(to, config: config)
|
|
183
|
+
to = in_config_zone(to, config: config)
|
|
184
184
|
distance = 0
|
|
185
185
|
while from < to
|
|
186
186
|
# look at working ranges
|
data/lib/working_hours/config.rb
CHANGED
|
@@ -44,9 +44,8 @@ module WorkingHours
|
|
|
44
44
|
validate_working_hours! config[:working_hours]
|
|
45
45
|
validate_holidays! config[:holidays]
|
|
46
46
|
validate_time_zone! config[:time_zone]
|
|
47
|
-
compiled = {working_hours:
|
|
47
|
+
compiled = { working_hours: Array.new(7) { Hash.new } }
|
|
48
48
|
working_hours.each do |day, hours|
|
|
49
|
-
compiled[:working_hours][DAYS_OF_WEEK.index(day)] = {}
|
|
50
49
|
hours.each do |start, finish|
|
|
51
50
|
compiled[:working_hours][DAYS_OF_WEEK.index(day)][compile_time(start)] = compile_time(finish)
|
|
52
51
|
end
|
|
@@ -129,6 +129,13 @@ describe WorkingHours::Computation do
|
|
|
129
129
|
time = Time.utc(2014, 4, 8, 0, 0, 30) # Tuesday
|
|
130
130
|
expect(add_seconds(time, -60)).to eq(Time.utc(2014, 4, 7, 23, 59, 00))
|
|
131
131
|
end
|
|
132
|
+
|
|
133
|
+
it 'honors miliseconds in the base time and increment (but return rounded result)' do
|
|
134
|
+
# Rounding the base time or increments before the end would yield a wrong result
|
|
135
|
+
time = Time.utc(1991, 11, 15, 16, 59, 42.25) # +250ms
|
|
136
|
+
expect(add_seconds(time, 120.4)).to eq(Time.utc(1991, 11, 18, 9, 1, 43))
|
|
137
|
+
end
|
|
138
|
+
|
|
132
139
|
end
|
|
133
140
|
|
|
134
141
|
describe '#advance_to_working_time' do
|
|
@@ -536,5 +543,20 @@ describe WorkingHours::Computation do
|
|
|
536
543
|
Time.new(2014, 4, 7, 15, 0, 0, "-04:00"), # Monday 7pm in UTC
|
|
537
544
|
)).to eq(7.hours)
|
|
538
545
|
end
|
|
546
|
+
|
|
547
|
+
# generates two times with +0ms, +250ms, +500ms, +750ms and +1s
|
|
548
|
+
# then for each combination compare the result with a ruby diff
|
|
549
|
+
context 'with precise miliseconds timings' do
|
|
550
|
+
reference = Time.utc(2014, 4, 7, 10)
|
|
551
|
+
0.step(1.0, 0.25) do |offset1|
|
|
552
|
+
0.step(1.0, 0.25) do |offset2|
|
|
553
|
+
from = reference + offset1
|
|
554
|
+
to = reference + offset2
|
|
555
|
+
it "returns expected value (#{(to - from).round}) for #{offset1} — #{offset2} interval" do
|
|
556
|
+
expect(working_time_between(from, to)).to eq((to - from).round)
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
end
|
|
560
|
+
end
|
|
539
561
|
end
|
|
540
562
|
end
|
|
@@ -266,16 +266,23 @@ describe WorkingHours::Config do
|
|
|
266
266
|
|
|
267
267
|
it 'computes an optimized version' do
|
|
268
268
|
expect(subject).to eq({
|
|
269
|
-
:working_hours => [
|
|
269
|
+
:working_hours => [{}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {}],
|
|
270
270
|
:holidays => Set.new([]),
|
|
271
271
|
:time_zone => ActiveSupport::TimeZone['UTC']
|
|
272
272
|
})
|
|
273
273
|
end
|
|
274
274
|
|
|
275
|
+
it 'includes default values for each days so computation does not fail' do
|
|
276
|
+
WorkingHours::Config.working_hours = {:mon => {'08:00' => '14:00'}}
|
|
277
|
+
expect(subject[:working_hours]).to eq([{}, {28800=>50400}, {}, {}, {}, {}, {}])
|
|
278
|
+
expect(WorkingHours.working_time_between(Time.utc(2014, 4, 14, 0), Time.utc(2014, 4, 21, 0))).to eq(3600*6)
|
|
279
|
+
expect(WorkingHours.add_seconds(Time.utc(2014, 4, 14, 0), 3600*7)).to eq(Time.utc(2014, 4, 21, 9))
|
|
280
|
+
end
|
|
281
|
+
|
|
275
282
|
it 'supports seconds' do
|
|
276
283
|
WorkingHours::Config.working_hours = {:mon => {'20:32:59' => '22:59:59'}}
|
|
277
284
|
expect(subject).to eq({
|
|
278
|
-
:working_hours => [
|
|
285
|
+
:working_hours => [{}, {73979 => 82799}, {}, {}, {}, {}, {}],
|
|
279
286
|
:holidays => Set.new([]),
|
|
280
287
|
:time_zone => ActiveSupport::TimeZone['UTC']
|
|
281
288
|
})
|
|
@@ -284,7 +291,7 @@ describe WorkingHours::Config do
|
|
|
284
291
|
it 'supports 24:00 (converts to 23:59:59.999999)' do
|
|
285
292
|
WorkingHours::Config.working_hours = {:mon => {'20:00' => '24:00'}}
|
|
286
293
|
expect(subject).to eq({
|
|
287
|
-
:working_hours => [
|
|
294
|
+
:working_hours => [{}, {72000 => 86399.999999}, {}, {}, {}, {}, {}],
|
|
288
295
|
:holidays => Set.new([]),
|
|
289
296
|
:time_zone => ActiveSupport::TimeZone['UTC']
|
|
290
297
|
})
|
|
@@ -296,9 +303,9 @@ describe WorkingHours::Config do
|
|
|
296
303
|
}.to change {
|
|
297
304
|
WorkingHours::Config.precompiled[:working_hours]
|
|
298
305
|
}.from(
|
|
299
|
-
[
|
|
306
|
+
[{}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {32400=>61200}, {}]
|
|
300
307
|
).to(
|
|
301
|
-
[
|
|
308
|
+
[{}, {28800=>50400}, {}, {}, {}, {}, {}]
|
|
302
309
|
)
|
|
303
310
|
end
|
|
304
311
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: working_hours
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adrien Jarthon
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2021-01-31 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
@@ -152,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
152
152
|
- !ruby/object:Gem::Version
|
|
153
153
|
version: '0'
|
|
154
154
|
requirements: []
|
|
155
|
-
rubygems_version: 3.0.
|
|
155
|
+
rubygems_version: 3.0.3
|
|
156
156
|
signing_key:
|
|
157
157
|
specification_version: 4
|
|
158
158
|
summary: time calculation with working hours
|