working_hours 1.4.0 → 1.5.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/.github/workflows/build.yml +38 -0
- data/CHANGELOG.md +11 -1
- data/README.md +18 -3
- data/gemfiles/{Gemfile.activesupport-4.x → Gemfile.activesupport-7.1.x} +1 -1
- data/gemfiles/{Gemfile.activesupport-5.x → Gemfile.activesupport-7.2.x} +1 -1
- data/gemfiles/{Gemfile.activesupport-6.x → Gemfile.activesupport-8.x} +1 -1
- data/lib/working_hours/config.rb +43 -15
- data/lib/working_hours/version.rb +1 -1
- data/spec/working_hours/computation_spec.rb +2 -2
- data/working_hours.gemspec +1 -1
- metadata +12 -12
- data/.travis.yml +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 225b5949f517f52c261b36052038b14c5041f68c14ead85872a3fe5f62221b22
|
4
|
+
data.tar.gz: 753f528212ba0c641390383a0d2446f6291ef5aabf581fd338034083bee0a012
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 979eb961fadd99a0997a361cc34f0e4d71df757a23103f40a76038dce547ea103f05c879eddf098b56af04eddb97dc297cbcae686a4026f2a09e94838dae6cb1
|
7
|
+
data.tar.gz: 93a6d6e4c69af754f593e69fb46afff7ea242bcccfb9c57627ede0bce4826d5bc25de1aaccb4ae4ed3c6b560929fa188871e2b6b342462bb154114ba21ddd1b6
|
@@ -0,0 +1,38 @@
|
|
1
|
+
name: build
|
2
|
+
on: push
|
3
|
+
jobs:
|
4
|
+
specs:
|
5
|
+
runs-on: ubuntu-latest
|
6
|
+
timeout-minutes: 10
|
7
|
+
strategy:
|
8
|
+
matrix:
|
9
|
+
ruby_version:
|
10
|
+
- 3.1.6
|
11
|
+
- 3.2.6
|
12
|
+
- 3.3.6
|
13
|
+
- jruby-9.4.9.0
|
14
|
+
gemfile:
|
15
|
+
- gemfiles/Gemfile.activesupport-7.1.x
|
16
|
+
- gemfiles/Gemfile.activesupport-7.2.x
|
17
|
+
- gemfiles/Gemfile.activesupport-8.x
|
18
|
+
exclude:
|
19
|
+
- gemfile: gemfiles/Gemfile.activesupport-8.x
|
20
|
+
ruby_version: 3.1.6
|
21
|
+
- gemfile: gemfiles/Gemfile.activesupport-8.x
|
22
|
+
ruby_version: jruby-9.4.9.0
|
23
|
+
env:
|
24
|
+
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
25
|
+
steps:
|
26
|
+
- name: Checkout code
|
27
|
+
uses: actions/checkout@v3
|
28
|
+
with:
|
29
|
+
fetch-depth: 0
|
30
|
+
|
31
|
+
- name: Setup Ruby
|
32
|
+
uses: ruby/setup-ruby@v1
|
33
|
+
with:
|
34
|
+
ruby-version: ${{ matrix.ruby_version }}
|
35
|
+
bundler-cache: true
|
36
|
+
|
37
|
+
- name: Run rspec
|
38
|
+
run: bundle exec rspec
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
-
[Compare master with v1.
|
3
|
+
[Compare master with v1.5.0](https://github.com/intrepidd/working_hours/compare/v1.5.0...master)
|
4
|
+
|
5
|
+
# v1.5.0
|
6
|
+
This release does not include any code change, there is only a dependency bump to ActiveSupport >= 7.0 to reflect the actual versions the gem supports.
|
7
|
+
|
8
|
+
* Drop support for unsupported Ruby & ActiveSupport versions
|
9
|
+
* Add support to ActiveSupport 7 and 8
|
10
|
+
* Changes gemspec dependency to ActiveSupport >= 7.0
|
11
|
+
|
12
|
+
# v1.4.1
|
13
|
+
* Add InvalidConfiguration error code to allow custom message or behavior - [#47](https://github.com/Intrepidd/working_hours/pull/47)
|
4
14
|
|
5
15
|
# v1.4.0
|
6
16
|
* New config option: holiday_hours - [#37](https://github.com/Intrepidd/working_hours/pull/37)
|
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# WorkingHours
|
2
2
|
|
3
|
-
[](https://github.com/Intrepidd/working_hours/actions/workflows/build.yml)
|
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 `
|
9
|
-
- ActiveSupport `
|
8
|
+
- Ruby `3.1`, `3.2`, `3.3`, JRuby `9.4`
|
9
|
+
- ActiveSupport `7.x`, `8.x`
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
@@ -116,6 +116,21 @@ If *any* hours are set for a calendar day in `holiday_hours`, then the `working_
|
|
116
116
|
WorkingHours::Config.holiday_hours = {Date.new(2020, 12, 24) => {'09:00' => '12:00', '13:00' => '15:00'}}
|
117
117
|
```
|
118
118
|
|
119
|
+
### Handling errors
|
120
|
+
|
121
|
+
If the configuration is erroneous, an ``WorkingHours::InvalidConfiguration`` exception will be raised containing the appropriate error message.
|
122
|
+
|
123
|
+
You can also access the error code in case you want to implement custom behavior or changing one specific message, e.g:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
rescue WorkingHours::InvalidConfiguration => e
|
127
|
+
if e.error_code == :empty
|
128
|
+
raise StandardError.new "Config is required"
|
129
|
+
end
|
130
|
+
raise e
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
119
134
|
## No core extensions / monkey patching
|
120
135
|
|
121
136
|
Core extensions (monkey patching to add methods on Time, Date, Numbers, etc.) are handy but not appreciated by everyone. WorkingHours can also be used **without any monkey patching**:
|
data/lib/working_hours/config.rb
CHANGED
@@ -1,7 +1,35 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
3
|
module WorkingHours
|
4
|
-
InvalidConfiguration
|
4
|
+
class InvalidConfiguration < StandardError
|
5
|
+
attr_reader :data, :error_code
|
6
|
+
|
7
|
+
def initialize(error_code, data: nil)
|
8
|
+
@data = data
|
9
|
+
@error_code = error_code
|
10
|
+
super compose_message(error_code)
|
11
|
+
end
|
12
|
+
|
13
|
+
def compose_message(error_code)
|
14
|
+
case error_code
|
15
|
+
when :empty then "No working hours given"
|
16
|
+
when :empty_day then "No working hours given for day `#{@data[:day]}`"
|
17
|
+
when :holidays_not_array then "Invalid type for holidays: #{@data[:holidays_class]} - must act like an array"
|
18
|
+
when :holiday_not_date then "Invalid holiday: #{@data[:day]} - must be Date"
|
19
|
+
when :invalid_day_keys then "Invalid day identifier(s): #{@data[:invalid_keys]} - must be 3 letter symbols"
|
20
|
+
when :invalid_format then "Invalid time: #{@data[:time]} - must be 'HH:MM(:SS)'"
|
21
|
+
when :invalid_holiday_keys then "Invalid day identifier(s): #{@data[:invalid_keys]} - must be a Date object"
|
22
|
+
when :invalid_timezone then "Invalid time zone: #{@data[:zone]} - must be String or ActiveSupport::TimeZone"
|
23
|
+
when :invalid_type then "Invalid type for `#{@data[:day]}`: #{@data[:hours_class]} - must be Hash"
|
24
|
+
when :outside_of_day then "Invalid time: #{@data[:time]} - outside of day"
|
25
|
+
when :overlap then "Invalid range: #{@data[:start]} => #{@data[:finish]} - overlaps previous range"
|
26
|
+
when :unknown_timezone then "Unknown time zone: #{@data[:zone]}"
|
27
|
+
when :wrong_order then "Invalid range: #{@data[:start]} => #{@data[:finish]} - ends before it starts"
|
28
|
+
else "Invalid Configuration"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
5
33
|
|
6
34
|
class Config
|
7
35
|
TIME_FORMAT = /\A([0-2][0-9])\:([0-5][0-9])(?:\:([0-5][0-9]))?\z/
|
@@ -149,22 +177,22 @@ module WorkingHours
|
|
149
177
|
def validate_hours! dates
|
150
178
|
dates.each do |day, hours|
|
151
179
|
if not hours.is_a? Hash
|
152
|
-
raise InvalidConfiguration.new
|
180
|
+
raise InvalidConfiguration.new :invalid_type, data: { day: day, hours_class: hours.class }
|
153
181
|
elsif hours.empty?
|
154
|
-
raise InvalidConfiguration.new
|
182
|
+
raise InvalidConfiguration.new :empty_day, data: { day: day }
|
155
183
|
end
|
156
184
|
last_time = nil
|
157
185
|
hours.sort.each do |start, finish|
|
158
186
|
if not start =~ TIME_FORMAT
|
159
|
-
raise InvalidConfiguration.new
|
187
|
+
raise InvalidConfiguration.new :invalid_format, data: { time: start }
|
160
188
|
elsif not finish =~ TIME_FORMAT
|
161
|
-
raise InvalidConfiguration.new
|
189
|
+
raise InvalidConfiguration.new :invalid_format, data: { time: finish }
|
162
190
|
elsif compile_time(finish) >= 24 * 60 * 60
|
163
|
-
raise InvalidConfiguration.new
|
191
|
+
raise InvalidConfiguration.new :outside_of_day, data: { time: finish }
|
164
192
|
elsif start >= finish
|
165
|
-
raise InvalidConfiguration.new
|
193
|
+
raise InvalidConfiguration.new :wrong_order, data: { start: start, finish: finish }
|
166
194
|
elsif last_time and start < last_time
|
167
|
-
raise InvalidConfiguration.new
|
195
|
+
raise InvalidConfiguration.new :overlap, data: { start: start, finish: finish }
|
168
196
|
end
|
169
197
|
last_time = finish
|
170
198
|
end
|
@@ -173,28 +201,28 @@ module WorkingHours
|
|
173
201
|
|
174
202
|
def validate_working_hours! week
|
175
203
|
if week.empty?
|
176
|
-
raise InvalidConfiguration.new
|
204
|
+
raise InvalidConfiguration.new :empty
|
177
205
|
end
|
178
206
|
if (invalid_keys = (week.keys - DAYS_OF_WEEK)).any?
|
179
|
-
raise InvalidConfiguration.new
|
207
|
+
raise InvalidConfiguration.new :invalid_day_keys, data: { invalid_keys: invalid_keys.join(', ') }
|
180
208
|
end
|
181
209
|
validate_hours!(week)
|
182
210
|
end
|
183
211
|
|
184
212
|
def validate_holiday_hours! days
|
185
213
|
if (invalid_keys = (days.keys.reject{ |day| day.is_a?(Date) })).any?
|
186
|
-
raise InvalidConfiguration.new
|
214
|
+
raise InvalidConfiguration.new :invalid_holiday_keys, data: { invalid_keys: invalid_keys.join(', ') }
|
187
215
|
end
|
188
216
|
validate_hours!(days)
|
189
217
|
end
|
190
218
|
|
191
219
|
def validate_holidays! holidays
|
192
220
|
if not holidays.respond_to?(:to_a)
|
193
|
-
raise InvalidConfiguration.new
|
221
|
+
raise InvalidConfiguration.new :holidays_not_array, data: { holidays_class: holidays.class }
|
194
222
|
end
|
195
223
|
holidays.to_a.each do |day|
|
196
224
|
if not day.is_a? Date
|
197
|
-
raise InvalidConfiguration.new
|
225
|
+
raise InvalidConfiguration.new :holiday_not_date, data: { day: day }
|
198
226
|
end
|
199
227
|
end
|
200
228
|
end
|
@@ -203,12 +231,12 @@ module WorkingHours
|
|
203
231
|
if zone.is_a? String
|
204
232
|
res = ActiveSupport::TimeZone[zone]
|
205
233
|
if res.nil?
|
206
|
-
raise InvalidConfiguration.new
|
234
|
+
raise InvalidConfiguration.new :unknown_timezone, data: { zone: zone }
|
207
235
|
end
|
208
236
|
elsif zone.is_a? ActiveSupport::TimeZone
|
209
237
|
res = zone
|
210
238
|
else
|
211
|
-
raise InvalidConfiguration.new
|
239
|
+
raise InvalidConfiguration.new :invalid_timezone, data: { zone: zone.inspect }
|
212
240
|
end
|
213
241
|
res
|
214
242
|
end
|
@@ -401,12 +401,12 @@ describe WorkingHours::Computation do
|
|
401
401
|
|
402
402
|
it 'takes into account reduced holiday closing' do
|
403
403
|
WorkingHours::Config.holiday_hours = { Date.new(2019, 12, 27) => { '10:00' => '17:00' } }
|
404
|
-
expect(advance_to_closing_time(Time.
|
404
|
+
expect(advance_to_closing_time(Time.utc(2019, 12, 26, 20))).to eq(Time.utc(2019, 12, 27, 17))
|
405
405
|
end
|
406
406
|
|
407
407
|
it 'takes into account extended holiday closing' do
|
408
408
|
WorkingHours::Config.holiday_hours = { Date.new(2019, 12, 26) => { '10:00' => '21:00' } }
|
409
|
-
expect(advance_to_closing_time(Time.
|
409
|
+
expect(advance_to_closing_time(Time.utc(2019, 12, 26, 20))).to eq(Time.utc(2019, 12, 26, 21))
|
410
410
|
end
|
411
411
|
end
|
412
412
|
|
data/working_hours.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency 'activesupport', '>=
|
21
|
+
spec.add_dependency 'activesupport', '>= 7.0'
|
22
22
|
spec.add_dependency 'tzinfo'
|
23
23
|
|
24
24
|
spec.add_development_dependency 'bundler', '>= 1.5'
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: working_hours
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adrien Jarthon
|
8
8
|
- Intrepidd
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-11-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '7.0'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '7.0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: tzinfo
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,17 +103,17 @@ executables: []
|
|
103
103
|
extensions: []
|
104
104
|
extra_rdoc_files: []
|
105
105
|
files:
|
106
|
+
- ".github/workflows/build.yml"
|
106
107
|
- ".gitignore"
|
107
108
|
- ".rspec"
|
108
|
-
- ".travis.yml"
|
109
109
|
- CHANGELOG.md
|
110
110
|
- Gemfile
|
111
111
|
- LICENSE.txt
|
112
112
|
- README.md
|
113
113
|
- Rakefile
|
114
|
-
- gemfiles/Gemfile.activesupport-
|
115
|
-
- gemfiles/Gemfile.activesupport-
|
116
|
-
- gemfiles/Gemfile.activesupport-
|
114
|
+
- gemfiles/Gemfile.activesupport-7.1.x
|
115
|
+
- gemfiles/Gemfile.activesupport-7.2.x
|
116
|
+
- gemfiles/Gemfile.activesupport-8.x
|
117
117
|
- gemfiles/Gemfile.activesupport-edge
|
118
118
|
- lib/working_hours.rb
|
119
119
|
- lib/working_hours/computation.rb
|
@@ -137,7 +137,7 @@ homepage: https://github.com/intrepidd/working_hours
|
|
137
137
|
licenses:
|
138
138
|
- MIT
|
139
139
|
metadata: {}
|
140
|
-
post_install_message:
|
140
|
+
post_install_message:
|
141
141
|
rdoc_options: []
|
142
142
|
require_paths:
|
143
143
|
- lib
|
@@ -152,8 +152,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
152
|
- !ruby/object:Gem::Version
|
153
153
|
version: '0'
|
154
154
|
requirements: []
|
155
|
-
rubygems_version: 3.
|
156
|
-
signing_key:
|
155
|
+
rubygems_version: 3.5.10
|
156
|
+
signing_key:
|
157
157
|
specification_version: 4
|
158
158
|
summary: time calculation with working hours
|
159
159
|
test_files:
|
data/.travis.yml
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
dist: bionic
|
3
|
-
rvm:
|
4
|
-
- 2.4.10
|
5
|
-
- 2.5.8
|
6
|
-
- 2.6.6
|
7
|
-
- 2.7.2
|
8
|
-
- 3.0.0
|
9
|
-
- jruby-9.2.14.0
|
10
|
-
gemfile:
|
11
|
-
- gemfiles/Gemfile.activesupport-4.x
|
12
|
-
- gemfiles/Gemfile.activesupport-5.x
|
13
|
-
- gemfiles/Gemfile.activesupport-6.x
|
14
|
-
jobs:
|
15
|
-
exclude:
|
16
|
-
- rvm: 2.4.10
|
17
|
-
gemfile: gemfiles/Gemfile.activesupport-6.x
|
18
|
-
- rvm: 2.7.2
|
19
|
-
gemfile: gemfiles/Gemfile.activesupport-4.x
|
20
|
-
- rvm: 3.0.0
|
21
|
-
gemfile: gemfiles/Gemfile.activesupport-4.x
|
22
|
-
include:
|
23
|
-
- rvm: ruby-head
|
24
|
-
gemfile: gemfiles/Gemfile.activesupport-edge
|
25
|
-
allow_failures:
|
26
|
-
- gemfile: gemfiles/Gemfile.activesupport-edge
|
27
|
-
fast_finish: true
|