workpattern 0.3.4 → 0.6.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.
data/workpattern.gemspec CHANGED
@@ -1,25 +1,39 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- require "workpattern/version"
4
3
 
5
- Gem::Specification.new do |s|
6
- s.name = "workpattern"
7
- s.version = Workpattern::VERSION
8
- s.authors = ["Barrie Callender"]
9
- s.email = ["barrie@callenb.org"]
10
- s.homepage = ""
11
- s.summary = %q{temporal calculations}
12
- s.description = %q{Workpattern performs date calculations that take into account working and resting periods.}
4
+ require_relative "lib/workpattern/version"
13
5
 
14
- s.rubyforge_project = "workpattern"
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "workpattern"
8
+ spec.version = Workpattern::VERSION
9
+ spec.authors = ["Barrie Callender"]
10
+ spec.email = ["barrie@callenb.org"]
15
11
 
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.require_paths = ["lib"]
12
+ spec.summary = "Calculates dates and durations whilst taking into account working and non-working periods down to a minute"
13
+ spec.description = "Calculates dates and durations whilst taking into account working and non-working times down to a minute. Business working time with holidays are a breeze."
14
+ spec.homepage = "http://workpattern.org"
15
+ spec.license = "MIT"
16
+ spec.required_ruby_version = Gem::Requirement.new(">= 1.9.3")
20
17
 
21
- # specify any dependencies here; for example:
22
- # s.add_development_dependency "rspec"
23
- # s.add_runtime_dependency "rest-client"
24
- s.add_development_dependency('rake', ['~> 0.9.2'])
18
+ spec.metadata["homepage_url"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = "https://github.com/callenb/workpattern"
20
+ spec.metadata["changelog_uri"] = "https://workpattern.org/2021/02/25/changelog.html"
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
26
+ end
27
+ spec.require_paths = ["lib"]
28
+
29
+ # Uncomment to register a new dependency of your gem
30
+ # spec.add_dependency "example-gem", "~> 1.0"
31
+
32
+ # For more information and examples about making a new gem, checkout our
33
+ # guide at: https://bundler.io/guides/creating_gem.html
34
+ spec.add_runtime_dependency 'tzinfo'
35
+ spec.add_runtime_dependency 'sorted_set' if RUBY_VERSION >= "2.4"
36
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
37
+ spec.require_paths = ["lib"]
38
+
25
39
  end
metadata CHANGED
@@ -1,31 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: workpattern
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Barrie Callender
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-27 00:00:00.000000000 Z
11
+ date: 2021-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rake
14
+ name: tzinfo
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.9.2
20
- type: :development
19
+ version: '0'
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: 0.9.2
27
- description: Workpattern performs date calculations that take into account working
28
- and resting periods.
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sorted_set
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Calculates dates and durations whilst taking into account working and
42
+ non-working times down to a minute. Business working time with holidays are a breeze.
29
43
  email:
30
44
  - barrie@callenb.org
31
45
  executables: []
@@ -34,35 +48,33 @@ extra_rdoc_files: []
34
48
  files:
35
49
  - ".gitignore"
36
50
  - ".travis.yml"
37
- - CHANGELOG
51
+ - CHANGELOG.md
52
+ - CODE_OF_CONDUCT.md
38
53
  - Gemfile
39
54
  - Gemfile.lock
55
+ - LICENSE.txt
40
56
  - README.md
41
57
  - Rakefile
42
- - config/website.yml
43
58
  - lib/workpattern.rb
44
59
  - lib/workpattern/clock.rb
60
+ - lib/workpattern/constants.rb
45
61
  - lib/workpattern/day.rb
46
- - lib/workpattern/hour.rb
47
- - lib/workpattern/utility/base.rb
48
62
  - lib/workpattern/version.rb
49
63
  - lib/workpattern/week.rb
64
+ - lib/workpattern/week_pattern.rb
50
65
  - lib/workpattern/workpattern.rb
51
66
  - script/console
52
67
  - script/destroy
53
68
  - script/generate
54
69
  - script/txt2html
55
- - test/test_clock.rb
56
- - test/test_day.rb
57
- - test/test_helper.rb
58
- - test/test_hour.rb
59
- - test/test_week.rb
60
- - test/test_workpattern.rb
61
- - test/test_workpattern_module.rb
62
70
  - workpattern.gemspec
63
- homepage: ''
64
- licenses: []
65
- metadata: {}
71
+ homepage: http://workpattern.org
72
+ licenses:
73
+ - MIT
74
+ metadata:
75
+ homepage_url: http://workpattern.org
76
+ source_code_uri: https://github.com/callenb/workpattern
77
+ changelog_uri: https://workpattern.org/2021/02/25/changelog.html
66
78
  post_install_message:
67
79
  rdoc_options: []
68
80
  require_paths:
@@ -71,16 +83,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
83
  requirements:
72
84
  - - ">="
73
85
  - !ruby/object:Gem::Version
74
- version: '0'
86
+ version: 1.9.3
75
87
  required_rubygems_version: !ruby/object:Gem::Requirement
76
88
  requirements:
77
89
  - - ">="
78
90
  - !ruby/object:Gem::Version
79
91
  version: '0'
80
92
  requirements: []
81
- rubyforge_project: workpattern
82
- rubygems_version: 2.1.4
93
+ rubygems_version: 3.0.9
83
94
  signing_key:
84
95
  specification_version: 4
85
- summary: temporal calculations
96
+ summary: Calculates dates and durations whilst taking into account working and non-working
97
+ periods down to a minute
86
98
  test_files: []
data/CHANGELOG DELETED
@@ -1,35 +0,0 @@
1
- ## Workpattern v0.3.4 (Sep 27, 2013) ##
2
-
3
- * diff doesn't calculate properly from working to resting day (#15) * Barrie Callender *
4
-
5
-
6
- ## Workpattern v0.3.3 (Sep 23, 2013) ##
7
-
8
- * Failed to subtract 1 minute from end of resting hour (#12) * Barrie Callender *
9
- * Failed to add minutes starting from a resting period in a patterned hour (#13) * Barrie Callender *
10
- * Failed to subtract the exact amount of minutes from a patterned hour (#14) * Barrie Callender *
11
- * The two tests no longer fail with Ruby 2.0 (#11) * Barrie Callender *
12
-
13
-
14
- ## Workpattern v0.3.2 (Mar 14, 2013) ##
15
-
16
- * Changed methods on Hour module so as to not clash with Rails (#10) * Barrie Callender *
17
- * Applied DRY principle to workpattern method in Workpattern class * Barrie Callender *
18
- * Removed file from emacs backup * Barrie Callender *
19
-
20
- ## Workpattern v0.3.1 (Oct 14, 2012) ##
21
-
22
- * RDOC documentation not right on rubydoc.info (#5) * Barrie Callender *
23
-
24
- ## Workpattern v0.3.0 (Jul 19, 2012) ##
25
-
26
- * incomplete tests for week (#2) * Barrie Callender *
27
- * getting wrong time when hour had exactly the right number of minutes (#9) * Barrie Callender *
28
- * jruby-19mode failed with SystemStackError: stack level too deep (#8) * Barrie Callender *
29
- * midnight flag should override hour and minutes (#7) * Barrie Callender *
30
- * available minutes not calculating correctly for a time of 00:01 (#6) * Barrie Callender *
31
-
32
- ## Workpattern v0.2.0 (May 31, 2012) ##
33
-
34
- * Rewritten from scratch effectively first version * Barrie Callender *
35
- * Please discard any version of Workpattern before this - some poor souls may have come across v0.1.0. - sorry! * Barrie Callender *
data/config/website.yml DELETED
@@ -1,2 +0,0 @@
1
- host: callenb@rubyforge.org
2
- remote_dir: /var/www/gforge-projects/workpattern
@@ -1,209 +0,0 @@
1
- module Workpattern
2
-
3
- # Represents the 60 minutes of an hour using an <tt>Integer</tt>
4
- #
5
- # @since 0.2.0
6
- #
7
- module Hour
8
-
9
- # Returns the total working minutes in the hour
10
- #
11
- # @return [Integer] working minutes in the hour
12
- #
13
- def wp_total
14
- return wp_minutes(0,59)
15
- end
16
-
17
- # Sets the minutes to either working (type=1) or resting (type=0)
18
- #
19
- # @param [Integer] start minute at start of range
20
- # @param [Integer] finish minute at end of range
21
- # @param [Integer] type defines whether working (1) or resting (0)
22
- #
23
- def wp_workpattern(start,finish,type=1)
24
- return wp_working(start,finish) if type==1
25
- return wp_resting(start,finish) if type==0
26
- end
27
-
28
- # Returns the first working minute in the hour or 60 if there are no working minutes
29
- #
30
- # @return [Integer] first working minute or 60 if none found
31
- #
32
- def wp_first
33
- 0.upto(59) {|minute| return minute if self.wp_minutes(minute,minute)==1}
34
- return nil
35
- end
36
-
37
- # Returns the last working minute in the hour or nil if there are no working minutes
38
- #
39
- # @return [Integer] last working minute or nil if none found
40
- #
41
- def wp_last
42
- 59.downto(0) {|minute| return minute if self.wp_minutes(minute,minute)==1}
43
- return nil
44
- end
45
-
46
- # Returns true if the given minute is working and false if it isn't
47
- #
48
- # @param [Integer] start is the minute being tested
49
- # @return [Boolean] true if minute is working, otherwise false
50
- #
51
- def wp_working?(start)
52
- return true if wp_minutes(start,start)==1
53
- return false
54
- end
55
-
56
- # Returns the total number of minutes between and including two minutes
57
- #
58
- # @param [Integer] start first minute in range
59
- # @param [Integer] finish last minute in range
60
- # @return [Integer] number of minutes from <tt>start</tt> to <tt>finish</tt> inclusive
61
- #
62
- def wp_minutes(start,finish)
63
- return (self & wp_mask(start,finish)).to_s(2).count('1')
64
- end
65
-
66
- # Returns the DateTime and remainding minutes when adding a duration to a minute in the hour.
67
- # A negative duration will subtract the minutes.
68
- #
69
- # @param [DateTime] time is the full date but only the minute element is used
70
- # @param [Integer] duration is the number of minutes to add and can be negative (subtraction)
71
- # @param [Boolean] next_hour used in subtraction to specify the starting point as midnight (00:00 the next day)
72
- # @return [DateTime,Integer,Boolean] The <tt>DateTime</tt> calculated along with remaining minutes and a flag indicating if starting point is next hour
73
- #
74
- def wp_calc(time,duration,next_hour=false)
75
- return wp_subtract(time,duration, next_hour) if duration < 0
76
- return wp_add(time,duration) if duration > 0
77
- return time,duration
78
- end
79
-
80
- # Returns the number of minutes between two minutes
81
- # @param [Integer] start first minute in range
82
- # @param [Integer] finish last minute in range
83
- # @return [Integer] number of working minutes in the range
84
- #
85
- def wp_diff(start,finish)
86
- start,finish=finish,start if start > finish
87
- return 0 if start==finish
88
- return (self & wp_mask(start,finish-1)).to_s(2).count('1')
89
- end
90
-
91
- private
92
-
93
- # Sets a working pattern
94
- #
95
- # @param [Integer] start is first minute in the range
96
- # @param [Integer] finish is last minute in the range
97
- #
98
- def wp_working(start,finish)
99
- return self | wp_mask(start,finish)
100
- end
101
-
102
- # sets a resting pattern
103
- #
104
- # @param [Integer] start is first minute in the range
105
- # @param [Integer] finish is last minute in the range
106
- #
107
- def wp_resting(start,finish)
108
- return self & ((2**60-1)-wp_mask(start,finish))
109
- end
110
-
111
- # Creates a bit mask of 1's over the specified range
112
- #
113
- # @param [Integer] start is first minute in the range
114
- # @param [Integer] finish is the last minute in the range
115
- #
116
- def wp_mask(start,finish)
117
- return ((2**(finish+1)-1)-(2**start-1))
118
- end
119
-
120
- # Handles the addition of minutes to a time
121
- #
122
- # @param [DateTime] time is the full date but only the minute element is used
123
- # @param [Integer] duration is the number of minutes to add and can be negative (subtraction)
124
- # @return [DateTime, Integer] The resulting DateTime and any remaining minutes
125
- #
126
- def wp_add(time,duration)
127
- start = time.min
128
- available_minutes=wp_minutes(start,59)
129
-
130
- if not_enough_minutes duration, available_minutes
131
- result_date = time + HOUR - (MINUTE*start)
132
- result_remainder = duration-available_minutes
133
- elsif exact_amount_of_minutes(start,duration)
134
- result_date = time + (MINUTE*duration)
135
- result_remainder = 0
136
- else # more than enough minutes
137
- step = start + duration
138
- duration-=wp_minutes(start,step)
139
- until (duration==0)
140
- step+=1
141
- duration-=wp_minutes(step,step)
142
- end
143
- step+=1
144
- result_date = time - (MINUTE*time.min) + (MINUTE*step)
145
- result_remainder = 0
146
- end
147
- return result_date, result_remainder
148
- end
149
-
150
- # Handles the subtraction of minutes from a time.
151
- # @param [DateTime] time is the full date but only the minute element is used
152
- # @param [Integer] duration is the number of minutes to add and can be negative (subtraction)
153
- # @param [Boolean] next_hour indicates if the 59th second is the first one to be included
154
- # @return [DateTime, Integer] The resulting DateTime and any remaining minutes
155
- #
156
- def wp_subtract(time,duration,next_hour)
157
- if next_hour
158
- if wp_working?(59)
159
- duration+=1
160
- time=time+(MINUTE*59)
161
- return wp_calc(time,duration)
162
- end
163
- return time, duration if wp_total==0
164
- else
165
- start=time.min
166
- available_minutes=0
167
- available_minutes = wp_minutes(0,start-1) if start > 0
168
- end
169
-
170
- if not_enough_minutes duration,available_minutes
171
- result_date = time - (MINUTE*start)
172
- result_remainder = duration+available_minutes
173
- elsif duration.abs==available_minutes
174
- result_date = time - (MINUTE*(start-wp_first))
175
- result_remainder = 0
176
- else
177
- step = start + duration
178
- duration+=wp_minutes(step,start-1)
179
- until (duration==0)
180
- step-=1
181
- duration+=wp_minutes(step,step)
182
- end
183
- result_date = time - (MINUTE * (start-step))
184
- result_remainder = 0
185
- end
186
- return result_date, result_remainder
187
-
188
- end
189
-
190
- private
191
-
192
- def not_enough_minutes(duration,available_minutes)
193
- return true if (duration.abs-available_minutes)>0
194
- return false
195
- end
196
-
197
- def exact_amount_of_minutes(start,duration)
198
- return true if wp_minutes(start,start+duration-1)==duration
199
- false
200
- end
201
- end
202
- end
203
-
204
- # Hours are represented by a bitwise <tt>Integer</tt> class so the code is mixed in to that class
205
- # @ since 0.3.0
206
- #
207
- class Integer
208
- include Workpattern::Hour
209
- end
@@ -1,32 +0,0 @@
1
- module Workpattern
2
-
3
- # Mixins expected to be used in more than one class
4
- #
5
- # @since 0.2.0
6
- #
7
- module Utility
8
-
9
- # Returns the supplied <tt>DateTime</tt> at the very start of the day.
10
- #
11
- # @param [DateTime] adate is the <tt>DateTime</tt> to be changed
12
- # @return [DateTime]
13
- #
14
- # @todo Consider mixin for DateTime class
15
- #
16
- def midnight_before(adate)
17
- return adate -(HOUR * adate.hour) - (MINUTE * adate.min)
18
- end
19
-
20
- # Returns the supplied <tt>DateTime</tt> at the very start of the next day.
21
- #
22
- # @param [DateTime] adate is the <tt>DateTime</tt> to be changed
23
- # @return [DateTime]
24
- #
25
- # @todo Consider mixin for DateTime class
26
- #
27
- def midnight_after(adate)
28
- return midnight_before(adate.next_day)
29
- end
30
-
31
- end
32
- end