workpattern 0.3.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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