workpattern 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +6 -0
- data/Rakefile +9 -0
- data/lib/workpattern.rb +1 -1
- data/lib/workpattern/clock.rb +10 -6
- data/lib/workpattern/day.rb +70 -51
- data/lib/workpattern/hour.rb +16 -19
- data/lib/workpattern/version.rb +1 -1
- data/lib/workpattern/week.rb +122 -100
- data/lib/workpattern/workpattern.rb +29 -41
- data/test/test_clock.rb +1 -0
- data/test/test_day.rb +200 -164
- data/test/test_helper.rb +0 -1
- data/test/test_hour.rb +7 -0
- data/test/test_week.rb +330 -257
- data/test/test_workpattern_module.rb +2 -13
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a052375d1d21fb15b3ec113efeafa9f385613b5
|
4
|
+
data.tar.gz: e5187dbe1b5c5b497553d7d665cb785b02824fdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 296401d1f2ff0d938fd934050373f776d46cfaf199ae24c3951769d65bad804a511c23c032968179a5fb6e979137148a72dba8a471a36cfda45db5a8cde97aae
|
7
|
+
data.tar.gz: 6ae2c003e83b250e1a21efe10ad7e979e2bd93df64887791d14769f12a0ce8a273e985be30fb1633915e947e921e7fecd94de0202706bd2e598938f48d616232
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## Workpattern v0.3.6 (Mar 25, 2014) ##
|
2
|
+
|
3
|
+
* total minutes of week is zero when short week starting after Sunday (#17) * Barrie Callender *
|
4
|
+
* Subtracting starting from top of the hour and last minute is non working (#18) * Barrie Callender *
|
5
|
+
* Refactorings intended to make the code easier to read and easier to change - still more to do * Barrie Callender *
|
6
|
+
|
1
7
|
## Workpattern v0.3.5 (Sep 30, 2013) ##
|
2
8
|
|
3
9
|
* License missing from gemspec (#16) * Barrie Callender *
|
data/Rakefile
CHANGED
data/lib/workpattern.rb
CHANGED
@@ -88,7 +88,7 @@ module Workpattern
|
|
88
88
|
# @param [Integer] base Workpattern starts on the 1st January of this year.
|
89
89
|
# @param [Integer] span Workpattern spans this number of years ending on 31st December.
|
90
90
|
# @return [Workpattern]
|
91
|
-
#
|
91
|
+
# @raise [NameError] when trying to create a Workpattern with a name that already exists
|
92
92
|
# @since 0.2.0
|
93
93
|
#
|
94
94
|
def self.new(name=DEFAULT_WORKPATTERN_NAME, base=DEFAULT_BASE_YEAR, span=DEFAULT_SPAN)
|
data/lib/workpattern/clock.rb
CHANGED
@@ -29,11 +29,8 @@ module Workpattern
|
|
29
29
|
# @param [Integer] min number of minutes
|
30
30
|
#
|
31
31
|
def initialize(hour=0,min=0)
|
32
|
-
@hour=hour
|
33
|
-
@min=min
|
34
|
-
total_minutes = minutes
|
35
|
-
@hour=total_minutes.div(60)
|
36
|
-
@min=total_minutes % 60
|
32
|
+
@hour = total_minutes(hour,min).div(60)
|
33
|
+
@min = total_minutes(hour,min) % 60
|
37
34
|
end
|
38
35
|
|
39
36
|
# Returns the total number of minutes
|
@@ -41,7 +38,7 @@ module Workpattern
|
|
41
38
|
# @return [Integer] total minutes represented by the Clock object
|
42
39
|
#
|
43
40
|
def minutes
|
44
|
-
return (@hour
|
41
|
+
return total_minutes(@hour,@min)
|
45
42
|
end
|
46
43
|
|
47
44
|
# Returns the hour of the clock (0-23)
|
@@ -74,5 +71,12 @@ module Workpattern
|
|
74
71
|
def to_s
|
75
72
|
hour.to_s.concat(':').concat(min.to_s).concat(' ').concat(minutes.to_s)
|
76
73
|
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def total_minutes(hours, mins)
|
78
|
+
return (hours*60) + mins
|
79
|
+
end
|
80
|
+
|
77
81
|
end
|
78
82
|
end
|
data/lib/workpattern/day.rb
CHANGED
@@ -34,8 +34,6 @@ module Workpattern
|
|
34
34
|
hour=WORKING_HOUR if type==1
|
35
35
|
hour=RESTING_HOUR if type==0
|
36
36
|
@values=Array.new(@hours) {|index| hour }
|
37
|
-
|
38
|
-
set_attributes
|
39
37
|
end
|
40
38
|
|
41
39
|
# Creates a duplicate of the current <tt>Day</tt> instance.
|
@@ -44,25 +42,26 @@ module Workpattern
|
|
44
42
|
#
|
45
43
|
def duplicate
|
46
44
|
duplicate_day = Day.new()
|
47
|
-
duplicate_values=Array.new(
|
48
|
-
|
49
|
-
duplicate_values[index]
|
45
|
+
duplicate_values=Array.new(self.values.size)
|
46
|
+
self.values.each_index {|index|
|
47
|
+
duplicate_values[index]=self.values[index]
|
50
48
|
}
|
51
49
|
duplicate_day.values=duplicate_values
|
52
|
-
duplicate_day.hours =
|
53
|
-
duplicate_day.first_hour
|
54
|
-
duplicate_day.first_min
|
55
|
-
duplicate_day.last_hour
|
56
|
-
duplicate_day.last_min
|
57
|
-
duplicate_day.total =
|
50
|
+
duplicate_day.hours = self.hours
|
51
|
+
duplicate_day.first_hour=self.first_hour
|
52
|
+
duplicate_day.first_min=self.first_min
|
53
|
+
duplicate_day.last_hour=self.last_hour
|
54
|
+
duplicate_day.last_min=self.last_min
|
55
|
+
duplicate_day.total = self.total
|
58
56
|
duplicate_day.refresh
|
59
57
|
return duplicate_day
|
60
58
|
end
|
61
59
|
|
62
60
|
# Recalculates characteristics for this day
|
61
|
+
# no longer required as calculating individually is faster
|
63
62
|
#
|
64
63
|
def refresh
|
65
|
-
|
64
|
+
|
66
65
|
end
|
67
66
|
|
68
67
|
# Sets all minutes in a date range to be working or resting.
|
@@ -74,19 +73,19 @@ module Workpattern
|
|
74
73
|
def workpattern(start_time,finish_time,type)
|
75
74
|
|
76
75
|
if start_time.hour==finish_time.hour
|
77
|
-
|
76
|
+
self.values[start_time.hour]=self.values[start_time.hour].wp_workpattern(start_time.min,finish_time.min,type)
|
78
77
|
else
|
79
78
|
test_hour=start_time.hour
|
80
|
-
|
79
|
+
self.values[test_hour]=self.values[test_hour].wp_workpattern(start_time.min,59,type)
|
81
80
|
|
82
81
|
while ((test_hour+1)<finish_time.hour)
|
83
82
|
test_hour+=1
|
84
|
-
|
83
|
+
self.values[test_hour]=self.values[test_hour].wp_workpattern(0,59,type)
|
85
84
|
end
|
86
85
|
|
87
|
-
|
86
|
+
self.values[finish_time.hour]=self.values[finish_time.hour].wp_workpattern(0,finish_time.min,type)
|
88
87
|
end
|
89
|
-
|
88
|
+
|
90
89
|
end
|
91
90
|
|
92
91
|
# Calculates the result of adding <tt>duration</tt> to
|
@@ -166,38 +165,58 @@ module Workpattern
|
|
166
165
|
end
|
167
166
|
|
168
167
|
if (start_hour==finish_hour)
|
169
|
-
retval
|
168
|
+
retval=self.values[start_hour].wp_minutes(start_min,finish_min)
|
170
169
|
else
|
171
170
|
|
172
|
-
retval
|
171
|
+
retval=self.values[start_hour].wp_minutes(start_min,59)
|
173
172
|
while (start_hour+1<finish_hour)
|
174
|
-
retval
|
173
|
+
retval+=self.values[start_hour+1].wp_total
|
175
174
|
start_hour+=1
|
176
175
|
end
|
177
|
-
retval
|
176
|
+
retval+=self.values[finish_hour].wp_minutes(0,finish_min)
|
178
177
|
end
|
179
178
|
|
180
179
|
return retval
|
181
180
|
end
|
182
181
|
|
183
|
-
private
|
184
182
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
0.upto(
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
183
|
+
def first_hour
|
184
|
+
0.upto(self.hours-1) do |index|
|
185
|
+
return index if self.values[index].wp_total!=0
|
186
|
+
end
|
187
|
+
return nil
|
188
|
+
end
|
189
|
+
|
190
|
+
def first_min
|
191
|
+
0.upto(self.hours-1) do |index|
|
192
|
+
return self.values[index].wp_first if !self.values[index].wp_first.nil?
|
193
|
+
end
|
194
|
+
return nil
|
195
|
+
end
|
196
|
+
|
197
|
+
def last_hour
|
198
|
+
(self.hours-1).downto(0) do |index|
|
199
|
+
return index if self.values[index].wp_total!=0
|
200
|
+
end
|
201
|
+
return nil
|
202
|
+
end
|
203
|
+
|
204
|
+
def last_min
|
205
|
+
(self.hours-1).downto(0) do |index|
|
206
|
+
return self.values[index].wp_last if self.values[index].wp_total!=0
|
207
|
+
end
|
208
|
+
return nil
|
200
209
|
end
|
210
|
+
|
211
|
+
def total
|
212
|
+
total_minutes=0
|
213
|
+
0.upto(self.hours-1) do |index|
|
214
|
+
total_minutes+=self.values[index].wp_total
|
215
|
+
end
|
216
|
+
return total_minutes
|
217
|
+
end
|
218
|
+
private
|
219
|
+
|
201
220
|
|
202
221
|
# Returns the first working minute as a <tt>DateTime</tt> or <tt>oo:oo</tt>
|
203
222
|
# when there is no working minutes in the day. Used by the <tt>#subtract</tt> method
|
@@ -206,11 +225,11 @@ module Workpattern
|
|
206
225
|
# @return [DateTime] the first working time of the day
|
207
226
|
#
|
208
227
|
def first_working_minute(time)
|
209
|
-
if
|
228
|
+
if self.first_hour.nil?
|
210
229
|
return time - (HOUR*time.hour) - (MINUTE*time.min)
|
211
230
|
else
|
212
|
-
time = time - HOUR * (time.hour -
|
213
|
-
time = time - MINUTE * (time.min -
|
231
|
+
time = time - HOUR * (time.hour - self.first_hour)
|
232
|
+
time = time - MINUTE * (time.min - self.first_min )
|
214
233
|
return time
|
215
234
|
end
|
216
235
|
end
|
@@ -231,8 +250,8 @@ module Workpattern
|
|
231
250
|
else
|
232
251
|
return time.prev_day, duration,true
|
233
252
|
end
|
234
|
-
elsif (time.hour
|
235
|
-
time=time-(HOUR
|
253
|
+
elsif (time.hour==self.first_hour && time.min==self.first_min)
|
254
|
+
time=time-(HOUR*self.first_hour) - (MINUTE*self.first_min)
|
236
255
|
return time.prev_day, duration, true
|
237
256
|
elsif (time.min>0)
|
238
257
|
available_minutes=minutes(0,0,time.hour,time.min-1)
|
@@ -247,17 +266,17 @@ module Workpattern
|
|
247
266
|
duration=0
|
248
267
|
time=first_working_minute(time)
|
249
268
|
else
|
250
|
-
minutes_this_hour
|
269
|
+
minutes_this_hour=self.values[time.hour].wp_minutes(0,time.min-1)
|
251
270
|
this_hour=time.hour
|
252
271
|
until (duration==0)
|
253
272
|
if (minutes_this_hour<duration.abs)
|
254
273
|
duration+=minutes_this_hour
|
255
274
|
time = time - (MINUTE*time.min) - HOUR
|
256
275
|
this_hour-=1
|
257
|
-
minutes_this_hour
|
276
|
+
minutes_this_hour=self.values[this_hour].wp_total
|
258
277
|
else
|
259
278
|
next_hour=(time.min==0)
|
260
|
-
time,duration
|
279
|
+
time,duration=self.values[this_hour].wp_calc(time,duration, next_hour)
|
261
280
|
end
|
262
281
|
end
|
263
282
|
end
|
@@ -273,15 +292,15 @@ module Workpattern
|
|
273
292
|
# @return [DateTime,Integer] Calculated time along with any remaining duration
|
274
293
|
#
|
275
294
|
def add(time,duration)
|
276
|
-
available_minutes=minutes(time.hour,time.min
|
295
|
+
available_minutes=minutes(time.hour,time.min,self.hours-1,59)
|
277
296
|
if ((duration-available_minutes)>0) # not enough minutes left in the day
|
278
297
|
|
279
298
|
result_date= time.next_day - (HOUR*time.hour) - (MINUTE*time.min)
|
280
299
|
duration = duration - available_minutes
|
281
300
|
else
|
282
|
-
total
|
301
|
+
total=self.values[time.hour].wp_minutes(time.min,59)
|
283
302
|
if (total==duration) # this hour satisfies
|
284
|
-
result_date=time - (MINUTE*time.min) + (MINUTE
|
303
|
+
result_date=time - (MINUTE*time.min) + (MINUTE*self.values[time.hour].wp_last) + MINUTE
|
285
304
|
duration = 0
|
286
305
|
else
|
287
306
|
result_date = time
|
@@ -290,9 +309,9 @@ module Workpattern
|
|
290
309
|
duration-=total
|
291
310
|
result_date=result_date + HOUR - (MINUTE*result_date.min)
|
292
311
|
else
|
293
|
-
result_date,duration
|
312
|
+
result_date,duration=self.values[result_date.hour].wp_calc(result_date,duration)
|
294
313
|
end
|
295
|
-
total
|
314
|
+
total=self.values[result_date.hour].wp_total
|
296
315
|
end
|
297
316
|
end
|
298
317
|
end
|
@@ -317,7 +336,7 @@ module Workpattern
|
|
317
336
|
# @return [Integer] number of remaining working minutes
|
318
337
|
#
|
319
338
|
def minutes_left_in_hour(start)
|
320
|
-
return
|
339
|
+
return self.values[start.hour].wp_diff(start.min,60)
|
321
340
|
end
|
322
341
|
|
323
342
|
end
|
data/lib/workpattern/hour.rb
CHANGED
@@ -155,32 +155,28 @@ module Workpattern
|
|
155
155
|
#
|
156
156
|
def wp_subtract(time,duration,next_hour)
|
157
157
|
if next_hour
|
158
|
-
if wp_working?(59)
|
159
|
-
|
160
|
-
|
161
|
-
return wp_calc(time,duration)
|
162
|
-
end
|
163
|
-
return time, duration if wp_total==0
|
158
|
+
duration += 1 if wp_working?(59)
|
159
|
+
time = time + (MINUTE * 59)
|
160
|
+
return wp_calc(time,duration)
|
164
161
|
else
|
165
162
|
start=time.min
|
166
|
-
available_minutes=0
|
167
|
-
available_minutes = wp_minutes(0,start-1) if start > 0
|
163
|
+
start > 0 ? available_minutes = wp_minutes(0,start-1) : available_minutes=0
|
168
164
|
end
|
169
165
|
|
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))
|
166
|
+
if not_enough_minutes duration, available_minutes
|
167
|
+
result_date = time - (MINUTE * start)
|
168
|
+
result_remainder = duration + available_minutes
|
169
|
+
elsif duration.abs == available_minutes
|
170
|
+
result_date = time - (MINUTE * (start - wp_first))
|
175
171
|
result_remainder = 0
|
176
172
|
else
|
177
173
|
step = start + duration
|
178
|
-
duration+=wp_minutes(step,start-1)
|
179
|
-
until (duration==0)
|
180
|
-
step-=1
|
181
|
-
duration+=wp_minutes(step,step)
|
174
|
+
duration += wp_minutes(step, start - 1)
|
175
|
+
until (duration == 0)
|
176
|
+
step -= 1
|
177
|
+
duration += wp_minutes(step,step)
|
182
178
|
end
|
183
|
-
result_date = time - (MINUTE * (start-step))
|
179
|
+
result_date = time - (MINUTE * (start - step))
|
184
180
|
result_remainder = 0
|
185
181
|
end
|
186
182
|
return result_date, result_remainder
|
@@ -188,7 +184,8 @@ module Workpattern
|
|
188
184
|
end
|
189
185
|
|
190
186
|
private
|
191
|
-
|
187
|
+
|
188
|
+
|
192
189
|
def not_enough_minutes(duration,available_minutes)
|
193
190
|
return true if (duration.abs-available_minutes)>0
|
194
191
|
return false
|
data/lib/workpattern/version.rb
CHANGED
data/lib/workpattern/week.rb
CHANGED
@@ -44,17 +44,17 @@ module Workpattern
|
|
44
44
|
# @return [Week] a duplicated instance of the current <tt>Week</tt> object
|
45
45
|
#
|
46
46
|
def duplicate()
|
47
|
-
duplicate_week=Week.new(
|
48
|
-
duplicate_values=Array.new(
|
49
|
-
|
50
|
-
duplicate_values[index]
|
47
|
+
duplicate_week=Week.new(self.start,self.finish)
|
48
|
+
duplicate_values=Array.new(self.values.size)
|
49
|
+
self.values.each_index {|index|
|
50
|
+
duplicate_values[index]=self.values[index].duplicate
|
51
51
|
}
|
52
52
|
duplicate_week.values=duplicate_values
|
53
|
-
duplicate_week.days
|
54
|
-
duplicate_week.start
|
55
|
-
duplicate_week.finish
|
56
|
-
duplicate_week.week_total
|
57
|
-
duplicate_week.total
|
53
|
+
duplicate_week.days=self.days
|
54
|
+
duplicate_week.start=self.start
|
55
|
+
duplicate_week.finish=self.finish
|
56
|
+
duplicate_week.week_total=self.week_total
|
57
|
+
duplicate_week.total=self.total
|
58
58
|
duplicate_week.refresh
|
59
59
|
return duplicate_week
|
60
60
|
end
|
@@ -72,9 +72,9 @@ module Workpattern
|
|
72
72
|
# @param [DateTime] start is the new starting date for the <tt>Week</tt>
|
73
73
|
# @param [DateTime] finish is the new finish date for the <tt>Week</tt>
|
74
74
|
#
|
75
|
-
def adjust(
|
76
|
-
|
77
|
-
|
75
|
+
def adjust(start_date,finish_date)
|
76
|
+
self.start=DateTime.new(start_date.year,start_date.month,start_date.day)
|
77
|
+
self.finish=DateTime.new(finish_date.year,finish_date.month,finish_date.day)
|
78
78
|
refresh
|
79
79
|
end
|
80
80
|
|
@@ -87,7 +87,7 @@ module Workpattern
|
|
87
87
|
# @param [Integer] type where a 1 sets it to working and a 0 to resting
|
88
88
|
#
|
89
89
|
def workpattern(days,from_time,to_time,type)
|
90
|
-
DAYNAMES[days].each {|day|
|
90
|
+
DAYNAMES[days].each {|day| self.values[day].workpattern(from_time,to_time,type)}
|
91
91
|
refresh
|
92
92
|
end
|
93
93
|
|
@@ -97,11 +97,11 @@ module Workpattern
|
|
97
97
|
# @param [Integer] duration minutes to add or subtract
|
98
98
|
# @param [Boolean] midnight flag used for subtraction that indicates the start date is midnight
|
99
99
|
#
|
100
|
-
def calc(
|
101
|
-
return
|
102
|
-
return add(
|
103
|
-
return subtract(
|
104
|
-
return subtract(
|
100
|
+
def calc(start_date,duration, midnight=false)
|
101
|
+
return start_date,duration,false if duration==0
|
102
|
+
return add(start_date,duration) if duration > 0
|
103
|
+
return subtract(self.start,duration, midnight) if (self.total==0) && (duration <0)
|
104
|
+
return subtract(start_date,duration, midnight) if duration <0
|
105
105
|
end
|
106
106
|
|
107
107
|
# Comparison Returns an integer (-1, 0, or +1) if week is less than, equal to, or greater than other_week
|
@@ -109,9 +109,9 @@ module Workpattern
|
|
109
109
|
# @param [Week] other_week object to compare to
|
110
110
|
# @return [Integer] -1,0 or +1 if week is less than, equal to or greater than other_week
|
111
111
|
def <=>(other_week)
|
112
|
-
if
|
112
|
+
if self.start < other_week.start
|
113
113
|
return -1
|
114
|
-
elsif
|
114
|
+
elsif self.start == other_week.start
|
115
115
|
return 0
|
116
116
|
else
|
117
117
|
return 1
|
@@ -123,8 +123,8 @@ module Workpattern
|
|
123
123
|
# @param [DateTime] start DateTime to be tested
|
124
124
|
# @return [Boolean] true if the minute is working otherwise false if it is a resting minute
|
125
125
|
#
|
126
|
-
def working?(
|
127
|
-
|
126
|
+
def working?(start_date)
|
127
|
+
self.values[start_date.wday].working?(start_date)
|
128
128
|
end
|
129
129
|
|
130
130
|
# Returns the difference in minutes between two DateTime values.
|
@@ -133,41 +133,50 @@ module Workpattern
|
|
133
133
|
# @param [DateTime] finish ending DateTime
|
134
134
|
# @return [Integer, DateTime] number of minutes and start date for rest of calculation.
|
135
135
|
#
|
136
|
-
def diff(
|
137
|
-
|
136
|
+
def diff(start_date,finish_date)
|
137
|
+
start_date,finish_date=finish_date,start_date if ((start_date <=> finish_date))==1
|
138
138
|
# calculate to end of day
|
139
139
|
#
|
140
|
-
if (
|
141
|
-
duration,
|
142
|
-
elsif (
|
143
|
-
duration,
|
140
|
+
if (start_date.jd==finish_date.jd) # same day
|
141
|
+
duration, start_date=self.values[start_date.wday].diff(start_date,finish_date)
|
142
|
+
elsif (finish_date.jd<=self.finish.jd) #within this week
|
143
|
+
duration, start_date=diff_detail(start_date,finish_date,finish_date)
|
144
144
|
else # after this week
|
145
|
-
duration,
|
145
|
+
duration, start_date=diff_detail(start_date,finish_date,self.finish)
|
146
146
|
end
|
147
|
-
return duration,
|
147
|
+
return duration, start_date
|
148
148
|
end
|
149
|
-
|
149
|
+
|
150
|
+
def week_total
|
151
|
+
span_in_days > 6 ? self.values.inject(0) {|sum,x| sum + x.total } : day_indexes.inject(0) {|sum,x| sum + self.values[x].total}
|
152
|
+
end
|
153
|
+
|
154
|
+
def total
|
155
|
+
total_days = span_in_days
|
156
|
+
return week_total if total_days < 8
|
157
|
+
sum = total_hours(self.start.wday,6)
|
158
|
+
total_days -= (7-self.start.wday)
|
159
|
+
sum += total_hours(0,self.finish.wday)
|
160
|
+
total_days-=(self.finish.wday+1)
|
161
|
+
sum += week_total * total_days / 7
|
162
|
+
return sum
|
163
|
+
end
|
164
|
+
|
150
165
|
private
|
166
|
+
|
167
|
+
def day_indexes
|
168
|
+
self.start.wday > self.finish.wday ? self.start.wday.upto(6).to_a.concat(0.upto(self.finish.wday).to_a) : self.start.wday.upto(self.finish.wday).to_a
|
169
|
+
end
|
170
|
+
|
151
171
|
|
172
|
+
def span_in_days
|
173
|
+
(self.finish-self.start).to_i + 1
|
174
|
+
end
|
175
|
+
|
152
176
|
# Recalculates all the attributes for a Week object
|
153
177
|
#
|
154
178
|
def set_attributes
|
155
|
-
|
156
|
-
@week_total=0
|
157
|
-
days=(@finish-@start).to_i + 1 #/60/60/24+1
|
158
|
-
if (7-@start.wday) < days and days < 8
|
159
|
-
@total+=total_hours(@start.wday,@finish.wday)
|
160
|
-
@week_total=@total
|
161
|
-
else
|
162
|
-
@total+=total_hours(@start.wday,6)
|
163
|
-
days -= (7-@start.wday)
|
164
|
-
@total+=total_hours(0,@finish.wday)
|
165
|
-
days-=(@finish.wday+1)
|
166
|
-
@week_total=@total if days==0
|
167
|
-
week_total=total_hours(0,6)
|
168
|
-
@total+=week_total * days / 7
|
169
|
-
@week_total=week_total if days != 0
|
170
|
-
end
|
179
|
+
|
171
180
|
end
|
172
181
|
|
173
182
|
# Calculates the total number of minutes between two dates
|
@@ -179,7 +188,7 @@ module Workpattern
|
|
179
188
|
def total_hours(start,finish)
|
180
189
|
total=0
|
181
190
|
start.upto(finish) {|day|
|
182
|
-
total
|
191
|
+
total+=self.values[day].total
|
183
192
|
}
|
184
193
|
return total
|
185
194
|
end
|
@@ -194,38 +203,38 @@ module Workpattern
|
|
194
203
|
#
|
195
204
|
def add(start,duration)
|
196
205
|
# aim to calculate to the end of the day
|
197
|
-
start,duration =
|
198
|
-
return start,duration,false if (duration==0) || (start.jd >
|
206
|
+
start,duration = self.values[start.wday].calc(start,duration)
|
207
|
+
return start,duration,false if (duration==0) || (start.jd > self.finish.jd)
|
199
208
|
# aim to calculate to the end of the next week day that is the same as @finish
|
200
|
-
while((duration!=0) && (start.wday
|
201
|
-
if (duration
|
202
|
-
duration = duration -
|
209
|
+
while((duration!=0) && (start.wday!=self.finish.next_day.wday) && (start.jd <= self.finish.jd))
|
210
|
+
if (duration>self.values[start.wday].total)
|
211
|
+
duration = duration - self.values[start.wday].total
|
203
212
|
start=start.next_day
|
204
|
-
elsif (duration
|
213
|
+
elsif (duration==self.values[start.wday].total)
|
205
214
|
start=after_last_work(start)
|
206
215
|
duration = 0
|
207
216
|
else
|
208
|
-
start,duration =
|
217
|
+
start,duration = self.values[start.wday].calc(start,duration)
|
209
218
|
end
|
210
219
|
end
|
211
220
|
|
212
|
-
return start,duration,false if (duration==0) || (start.jd >
|
221
|
+
return start,duration,false if (duration==0) || (start.jd > self.finish.jd)
|
213
222
|
|
214
223
|
# while duration accomodates full weeks
|
215
|
-
while ((duration!=0) && (duration
|
216
|
-
duration=duration -
|
224
|
+
while ((duration!=0) && (duration>=self.week_total) && ((start.jd+6) <= self.finish.jd))
|
225
|
+
duration=duration - self.week_total
|
217
226
|
start=start+7
|
218
227
|
end
|
219
228
|
|
220
|
-
return start,duration,false if (duration==0) || (start.jd >
|
229
|
+
return start,duration,false if (duration==0) || (start.jd > self.finish.jd)
|
221
230
|
|
222
231
|
# while duration accomodates full days
|
223
|
-
while ((duration!=0) && (start.jd<=
|
224
|
-
if (duration
|
225
|
-
duration = duration -
|
232
|
+
while ((duration!=0) && (start.jd<= self.finish.jd))
|
233
|
+
if (duration>self.values[start.wday].total)
|
234
|
+
duration = duration - self.values[start.wday].total
|
226
235
|
start=start.next_day
|
227
236
|
else
|
228
|
-
start,duration =
|
237
|
+
start,duration = self.values[start.wday].calc(start,duration)
|
229
238
|
end
|
230
239
|
end
|
231
240
|
return start, duration, false
|
@@ -249,47 +258,47 @@ module Workpattern
|
|
249
258
|
end
|
250
259
|
|
251
260
|
# aim to calculate to the start of the day
|
252
|
-
start,duration, midnight =
|
261
|
+
start,duration, midnight = self.values[start.wday].calc(start,duration)
|
253
262
|
|
254
|
-
if midnight && (start.jd >=
|
263
|
+
if midnight && (start.jd >= self.start.jd)
|
255
264
|
start,duration=minute_b4_midnight(start,duration)
|
256
265
|
return subtract(start,duration, false)
|
257
266
|
elsif midnight
|
258
267
|
return start,duration,midnight
|
259
|
-
elsif (duration==0) || (start.jd
|
268
|
+
elsif (duration==0) || (start.jd ==self.start.jd)
|
260
269
|
return start,duration, midnight
|
261
270
|
end
|
262
271
|
|
263
272
|
# aim to calculate to the start of the previous week day that is the same as @start
|
264
|
-
while((duration!=0) && (start.wday
|
273
|
+
while((duration!=0) && (start.wday!=self.start.wday) && (start.jd >= self.start.jd))
|
265
274
|
|
266
|
-
if (duration.abs
|
267
|
-
duration = duration +
|
275
|
+
if (duration.abs>=self.values[start.wday].total)
|
276
|
+
duration = duration + self.values[start.wday].total
|
268
277
|
start=start.prev_day
|
269
278
|
else
|
270
279
|
start,duration=minute_b4_midnight(start,duration)
|
271
|
-
start,duration =
|
280
|
+
start,duration = self.values[start.wday].calc(start,duration)
|
272
281
|
end
|
273
282
|
end
|
274
283
|
|
275
|
-
return start,duration if (duration==0) || (start.jd
|
284
|
+
return start,duration if (duration==0) || (start.jd ==self.start.jd)
|
276
285
|
|
277
286
|
#while duration accomodates full weeks
|
278
|
-
while ((duration!=0) && (duration.abs
|
279
|
-
duration=duration +
|
287
|
+
while ((duration!=0) && (duration.abs>=self.week_total) && ((start.jd-6) >= self.start.jd))
|
288
|
+
duration=duration + self.week_total
|
280
289
|
start=start-7
|
281
290
|
end
|
282
291
|
|
283
|
-
return start,duration if (duration==0) || (start.jd
|
292
|
+
return start,duration if (duration==0) || (start.jd ==self.start.jd)
|
284
293
|
|
285
294
|
#while duration accomodates full days
|
286
|
-
while ((duration!=0) && (start.jd>=
|
287
|
-
if (duration.abs
|
288
|
-
duration = duration +
|
295
|
+
while ((duration!=0) && (start.jd>= self.start.jd))
|
296
|
+
if (duration.abs>=self.values[start.wday].total)
|
297
|
+
duration = duration + self.values[start.wday].total
|
289
298
|
start=start.prev_day
|
290
299
|
else
|
291
300
|
start,duration=minute_b4_midnight(start,duration)
|
292
|
-
start,duration =
|
301
|
+
start,duration = self.values[start.wday].calc(start,duration)
|
293
302
|
end
|
294
303
|
end
|
295
304
|
|
@@ -308,7 +317,7 @@ module Workpattern
|
|
308
317
|
def minute_b4_midnight(start,duration)
|
309
318
|
start -= start.hour * HOUR
|
310
319
|
start -= start.min * MINUTE
|
311
|
-
duration +=
|
320
|
+
duration += self.values[start.wday].minutes(23,59,23,59)
|
312
321
|
start = start.next_day - MINUTE
|
313
322
|
return start,duration
|
314
323
|
end
|
@@ -318,13 +327,13 @@ module Workpattern
|
|
318
327
|
# @param [DateTime] start is the current date
|
319
328
|
# @return [DateTime] the new date
|
320
329
|
#
|
321
|
-
def after_last_work(
|
322
|
-
if
|
323
|
-
return
|
330
|
+
def after_last_work(start_date)
|
331
|
+
if self.values[start_date.wday].last_hour.nil?
|
332
|
+
return start_date.next_day
|
324
333
|
else
|
325
|
-
|
326
|
-
|
327
|
-
return
|
334
|
+
start_date = start_date + HOUR * (self.values[start_date.wday].last_hour - start_date.hour)
|
335
|
+
start_date = start_date + MINUTE * (self.values[start_date.wday].last_min - start_date.min + 1)
|
336
|
+
return start_date
|
328
337
|
end
|
329
338
|
end
|
330
339
|
|
@@ -335,29 +344,42 @@ module Workpattern
|
|
335
344
|
# @param [DateTime] finish_on the range to be used in this Week object.
|
336
345
|
# @return [DateTime, Integer] new date for rest of calculation and total number of minutes calculated thus far.
|
337
346
|
#
|
338
|
-
def diff_detail(
|
339
|
-
|
340
|
-
|
347
|
+
def diff_detail(start_date,finish_date,finish_on_date)
|
348
|
+
|
349
|
+
duration, start_date=diff_in_day(start_date, finish_date)
|
350
|
+
return duration,start_date if start_date > finish_on_date
|
351
|
+
|
341
352
|
#rest of week to finish day
|
342
|
-
while (
|
343
|
-
duration
|
344
|
-
|
353
|
+
while (start_date.wday<finish_date.wday) do
|
354
|
+
duration+=day_total(start_date)
|
355
|
+
start_date=start_date.next_day
|
345
356
|
end
|
357
|
+
|
346
358
|
#weeks
|
347
|
-
while (
|
348
|
-
duration
|
349
|
-
|
359
|
+
while (start_date.jd+7<finish_on_date.jd) do
|
360
|
+
duration+=self.week_total
|
361
|
+
start_date+=7
|
350
362
|
end
|
363
|
+
|
351
364
|
#days
|
352
|
-
while (
|
353
|
-
duration
|
354
|
-
|
365
|
+
while (start_date.jd < finish_on_date.jd) do
|
366
|
+
duration+=day_total(start_date)
|
367
|
+
start_date=start_date.next_day
|
355
368
|
end
|
356
|
-
|
357
|
-
|
369
|
+
|
370
|
+
#day
|
371
|
+
day_duration, start_date=diff_in_day(start_date, finish_date)
|
358
372
|
duration+=day_duration
|
359
|
-
return duration,
|
373
|
+
return duration, start_date
|
360
374
|
end
|
361
375
|
|
376
|
+
def diff_in_day(start_date,finish_date)
|
377
|
+
return self.values[start_date.wday].diff(start_date,finish_date)
|
378
|
+
end
|
379
|
+
|
380
|
+
def day_total(start_date)
|
381
|
+
return self.values[start_date.wday].total
|
382
|
+
end
|
383
|
+
|
362
384
|
end
|
363
385
|
end
|