business_time 0.9.1 → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fa0158cf6f58b97d18d14f31f5e1fa969b880cd7
4
- data.tar.gz: f7144c2f47e4ce925c19d661715212469f278245
2
+ SHA256:
3
+ metadata.gz: e917428c31758c1ce02b1bfae4f1ab3c864e8b3eb3f12ec3556445c390506820
4
+ data.tar.gz: 1f8020bef45cdbdb1981fe9452633a427a202c7bc4d4f3390ca955b8f6c7a49c
5
5
  SHA512:
6
- metadata.gz: 015f73637a4d3958b08442811e12552edfb68a251c6b5624e57ed46ec8fc923f48a70105d3082da292ada0c4fe3eeda590a8b228b038fde1c2e513411561d1d6
7
- data.tar.gz: 7374e3d3c4264f29a5447408fb4932a2099af93b3e628a3f5a10a950ce27ea599fe624e3bd1158f564e66293e292177aadc6819e34db85a05a289c72568f72be
6
+ metadata.gz: 8ffe3ada04985e1f12d6eb8c011e6dcfd4c09f02dc589e82e73fac1571af3caad6c52c2e80d7e312eb05cbdf5eda1ce39a251e6df2378d389f9fc49884ab7a5c
7
+ data.tar.gz: 1c244d0e42b7222422e5b6d2317aa1bdf9f5339ee71cae551c7c9a406add3b84dc6eed57e8d58e19a21dce10af10ba96e521eeb124a327510ea1827a17d9e2c0
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = business_time
2
2
 
3
- {<img src="https://secure.travis-ci.org/bokmann/business_time.png" />}[http://travis-ci.org/bokmann/business_time]
3
+ {<img src="https://github.com/bokmann/business_time/workflows/CI/badge.svg" />}[https://github.com/bokmann/business_time/actions?query=workflow%3ACI]
4
4
 
5
5
  ActiveSupport gives us some great helpers so we can do things like:
6
6
 
@@ -61,6 +61,11 @@ We can adjust the start and end time of our business hours
61
61
  BusinessTime::Config.beginning_of_workday = "8:30 am"
62
62
  BusinessTime::Config.end_of_workday = "5:30 pm"
63
63
 
64
+ Or we can temporarily override the configured values
65
+ BusinessTime::Config.with(beginning_of_workday: "8 am", end_of_workday: "6 pm") do
66
+ 1.business_hour.from_now
67
+ end
68
+
64
69
  and we can add holidays that don't count as business days
65
70
  July 5 in 2010 is a monday that the U.S. takes off because our independence day falls on that Sunday.
66
71
  three_day_weekend = Date.parse("July 5th, 2010")
@@ -166,6 +171,7 @@ Timezone relative date handling gets more and more complicated every time you lo
166
171
 
167
172
  == Contributors
168
173
  * David Bock http://github.com/bokmann
174
+ * Ryan McGeary http://github.com/rmm5t
169
175
  * Enrico Bianco http://github.com/enricob
170
176
  * Arild Shirazi http://github.com/ashirazi
171
177
  * Piotr Jakubowski http://github.com/piotrj
@@ -220,4 +226,4 @@ I'm proud of the work in this gem; the stability is a big part of that. This ge
220
226
 
221
227
  == Copyright
222
228
 
223
- Copyright (c) 2010-2017 bokmann. See LICENSE for details.
229
+ Copyright (c) 2010-2021 bokmann. See LICENSE for details.
@@ -17,7 +17,29 @@ module BusinessTime
17
17
  end
18
18
 
19
19
  def after(time = Time.current)
20
- days = @days
20
+ non_negative_days? ? calculate_after(time, @days) : calculate_before(time, -@days)
21
+ end
22
+
23
+ alias_method :from_now, :after
24
+ alias_method :since, :after
25
+
26
+ def before(time = Time.current)
27
+ non_negative_days? ? calculate_before(time, @days) : calculate_after(time, -@days)
28
+ end
29
+
30
+ alias_method :ago, :before
31
+ alias_method :until, :before
32
+
33
+ private
34
+
35
+ def non_negative_days?
36
+ @days >= 0
37
+ end
38
+
39
+ def calculate_after(time, days)
40
+ if (time.is_a?(Time) || time.is_a?(DateTime)) && !time.workday?
41
+ time = Time.beginning_of_workday(time)
42
+ end
21
43
  while days > 0 || !time.workday?
22
44
  days -= 1 if time.workday?
23
45
  time += 1.day
@@ -30,11 +52,10 @@ module BusinessTime
30
52
  time
31
53
  end
32
54
 
33
- alias_method :from_now, :after
34
- alias_method :since, :after
35
-
36
- def before(time = Time.current)
37
- days = @days
55
+ def calculate_before(time, days)
56
+ if (time.is_a?(Time) || time.is_a?(DateTime)) && !time.workday?
57
+ time = Time.beginning_of_workday(time)
58
+ end
38
59
  while days > 0 || !time.workday?
39
60
  days -= 1 if time.workday?
40
61
  time -= 1.day
@@ -48,8 +69,5 @@ module BusinessTime
48
69
  end
49
70
  time
50
71
  end
51
-
52
- alias_method :ago, :before
53
- alias_method :until, :before
54
72
  end
55
73
  end
@@ -24,9 +24,24 @@ module BusinessTime
24
24
  end
25
25
 
26
26
  def after(time)
27
+ non_negative_hours? ? calculate_after(time, @hours) : calculate_before(time, -@hours)
28
+ end
29
+ alias_method :since, :after
30
+
31
+ def before(time)
32
+ non_negative_hours? ? calculate_before(time, @hours) : calculate_after(time, -@hours)
33
+ end
34
+
35
+ private
36
+
37
+ def non_negative_hours?
38
+ @hours >= 0
39
+ end
40
+
41
+ def calculate_after(time, hours)
27
42
  after_time = Time.roll_forward(time)
28
43
  # Step through the hours, skipping over non-business hours
29
- @hours.times do
44
+ hours.times do
30
45
  after_time = after_time + 1.hour
31
46
 
32
47
  if after_time.hour == 0 && after_time.min == 0 && after_time.sec == 0
@@ -44,12 +59,11 @@ module BusinessTime
44
59
  end
45
60
  after_time
46
61
  end
47
- alias_method :since, :after
48
62
 
49
- def before(time)
63
+ def calculate_before(time, hours)
50
64
  before_time = Time.roll_backward(time)
51
65
  # Step through the hours, skipping over non-business hours
52
- @hours.times do
66
+ hours.times do
53
67
  before_time = before_time - 1.hour
54
68
 
55
69
  if before_time.hour == 0 && before_time.min == 0 && before_time.sec == 0
@@ -47,15 +47,19 @@ module BusinessTime
47
47
  end
48
48
 
49
49
  def local_config
50
- Thread.current[:business_time_local_config]
50
+ local_config_stack.last
51
51
  end
52
52
 
53
53
  def local_config=(config)
54
- Thread.current[:business_time_local_config] = config
54
+ local_config_stack.last.replace(config)
55
+ end
56
+
57
+ def local_config_stack
58
+ Thread.current[:business_time_local_config] ||= []
55
59
  end
56
60
 
57
61
  def local_config?
58
- !local_config.nil?
62
+ !local_config_stack.empty?
59
63
  end
60
64
 
61
65
  def threadsafe_cattr_accessor(name)
@@ -76,23 +80,7 @@ module BusinessTime
76
80
  end
77
81
  end
78
82
 
79
- # You can set this yourself, either by the load method below, or
80
- # by saying
81
- # BusinessTime::Config.beginning_of_workday = "8:30 am"
82
- # someplace in the initializers of your application.
83
- threadsafe_cattr_reader :beginning_of_workday
84
-
85
- # You can set this yourself, either by the load method below, or
86
- # by saying
87
- # BusinessTime::Config.end_of_workday = "5:30 pm"
88
- # someplace in the initializers of your application.
89
- threadsafe_cattr_reader :end_of_workday
90
-
91
- # You can set this yourself, either by the load method below, or
92
- # by saying
93
- # BusinessTime::Config.work_week = [:sun, :mon, :tue, :wed, :thu]
94
- # someplace in the initializers of your application.
95
- threadsafe_cattr_accessor :work_week
83
+ threadsafe_cattr_reader :work_week
96
84
 
97
85
  # You can set this yourself, either by the load method below, or
98
86
  # by saying
@@ -114,6 +102,10 @@ module BusinessTime
114
102
  threadsafe_cattr_accessor :fiscal_month_offset
115
103
 
116
104
  class << self
105
+ # You can set this yourself, either by the load method below, or
106
+ # by saying
107
+ # BusinessTime::Config.end_of_workday = "5:30 pm"
108
+ # someplace in the initializers of your application.
117
109
  def end_of_workday(day=nil)
118
110
  if day
119
111
  wday = work_hours[int_to_wday(day.wday)]
@@ -123,6 +115,10 @@ module BusinessTime
123
115
  end
124
116
  end
125
117
 
118
+ # You can set this yourself, either by the load method below, or
119
+ # by saying
120
+ # BusinessTime::Config.beginning_of_workday = "8:30 am"
121
+ # someplace in the initializers of your application.
126
122
  def beginning_of_workday(day=nil)
127
123
  if day
128
124
  wday = work_hours[int_to_wday(day.wday)]
@@ -132,6 +128,10 @@ module BusinessTime
132
128
  end
133
129
  end
134
130
 
131
+ # You can set this yourself, either by the load method below, or
132
+ # by saying
133
+ # BusinessTime::Config.work_week = [:sun, :mon, :tue, :wed, :thu]
134
+ # someplace in the initializers of your application.
135
135
  def work_week=(days)
136
136
  config[:work_week] = days
137
137
  self._weekdays = nil
@@ -173,11 +173,11 @@ module BusinessTime
173
173
  end
174
174
 
175
175
  def with(config)
176
- self.local_config = config().dup
176
+ local_config_stack.push(config().dup)
177
177
  config.each { |k,v| send("#{k}=", v) } # calculations are done on setting
178
178
  yield
179
179
  ensure
180
- self.local_config = nil
180
+ local_config_stack.pop
181
181
  end
182
182
 
183
183
  def default_config
@@ -186,18 +186,23 @@ module BusinessTime
186
186
 
187
187
  private
188
188
 
189
+ DAY_NAMES = [
190
+ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'
191
+ ]
192
+ private_constant :DAY_NAMES
193
+
189
194
  def wday_to_int day_name
190
- lowercase_day_names = ::Time::RFC2822_DAY_NAME.map(&:downcase)
195
+ lowercase_day_names = DAY_NAMES.map(&:downcase)
191
196
  lowercase_day_names.find_index(day_name.to_s.downcase)
192
197
  end
193
198
 
194
199
  def int_to_wday num
195
- ::Time::RFC2822_DAY_NAME.map(&:downcase).map(&:to_sym)[num]
200
+ DAY_NAMES.map(&:downcase).map(&:to_sym)[num]
196
201
  end
197
202
 
198
203
  def reset
199
- self.config = default_config
200
- self.local_config = nil
204
+ local_config_stack.clear
205
+ self.config = default_config
201
206
  end
202
207
 
203
208
  def deep_dup(object)
@@ -169,5 +169,30 @@ module BusinessTime
169
169
  def during_business_hours?
170
170
  self.workday? && self.to_i.between?(Time.beginning_of_workday(self).to_i, Time.end_of_workday(self).to_i)
171
171
  end
172
+
173
+ def consecutive_workdays
174
+ workday? ? consecutive_days { |date| date.workday? } : []
175
+ end
176
+
177
+ def consecutive_non_working_days
178
+ !workday? ? consecutive_days { |date| !date.workday? } : []
179
+ end
180
+
181
+ private
182
+
183
+ def consecutive_days
184
+ days = []
185
+ date = self + 1.day
186
+ while yield(date)
187
+ days << date
188
+ date += 1.day
189
+ end
190
+ date = self - 1.day
191
+ while yield(date)
192
+ days << date
193
+ date -= 1.day
194
+ end
195
+ (days << self).sort
196
+ end
172
197
  end
173
198
  end
@@ -1,3 +1,3 @@
1
1
  module BusinessTime
2
- VERSION = "0.9.1"
2
+ VERSION = "0.11.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: business_time
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bokmann
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-04 00:00:00.000000000 Z
11
+ date: 2021-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.2.8
19
+ version: 3.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 4.2.8
26
+ version: 3.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: tzinfo
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sorted_set
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -122,7 +136,7 @@ homepage: https://github.com/bokmann/business_time
122
136
  licenses:
123
137
  - MIT
124
138
  metadata: {}
125
- post_install_message:
139
+ post_install_message:
126
140
  rdoc_options: []
127
141
  require_paths:
128
142
  - lib
@@ -137,9 +151,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
151
  - !ruby/object:Gem::Version
138
152
  version: '0'
139
153
  requirements: []
140
- rubyforge_project:
141
- rubygems_version: 2.6.11
142
- signing_key:
154
+ rubygems_version: 3.2.31
155
+ signing_key:
143
156
  specification_version: 4
144
157
  summary: Support for doing time math in business hours and days
145
158
  test_files: []