workpattern 0.3.5 → 0.3.6
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/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
|