workpattern 0.5.0 → 0.7.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 +5 -5
- data/.gitignore +9 -19
- data/.travis.yml +17 -12
- data/{CHANGELOG → CHANGELOG.md} +27 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +17 -20
- data/Rakefile +0 -0
- data/lib/workpattern/clock.rb +0 -0
- data/lib/workpattern/constants.rb +72 -0
- data/lib/workpattern/day.rb +268 -0
- data/lib/workpattern/version.rb +1 -1
- data/lib/workpattern/week.rb +135 -298
- data/lib/workpattern/week_pattern.rb +142 -0
- data/lib/workpattern/workpattern.rb +124 -132
- data/lib/workpattern.rb +25 -73
- data/script/console +0 -0
- data/script/destroy +0 -0
- data/script/generate +0 -0
- data/script/txt2html +0 -0
- data/workpattern.gemspec +41 -20
- metadata +20 -36
- data/lib/workpattern/utility/base.rb +0 -27
- data/test/test_clock.rb +0 -29
- data/test/test_helper.rb +0 -2
- data/test/test_week.rb +0 -532
- data/test/test_workpattern.rb +0 -307
- data/test/test_workpattern_module.rb +0 -88
data/lib/workpattern/week.rb
CHANGED
|
@@ -8,18 +8,36 @@ module Workpattern
|
|
|
8
8
|
#
|
|
9
9
|
# @private
|
|
10
10
|
class Week
|
|
11
|
-
attr_accessor :
|
|
11
|
+
attr_accessor :hours_per_day, :start, :finish, :days
|
|
12
12
|
|
|
13
|
-
def initialize(start, finish, type =
|
|
13
|
+
def initialize(start, finish, type = WORK_TYPE, hours_per_day = HOURS_IN_DAY)
|
|
14
14
|
@hours_per_day = hours_per_day
|
|
15
15
|
@start = Time.gm(start.year, start.month, start.day)
|
|
16
16
|
@finish = Time.gm(finish.year, finish.month, finish.day)
|
|
17
|
-
@
|
|
18
|
-
|
|
19
|
-
@
|
|
17
|
+
@days = Array.new(LAST_DAY_OF_WEEK + 1)
|
|
18
|
+
FIRST_DAY_OF_WEEK.upto(LAST_DAY_OF_WEEK) do |i|
|
|
19
|
+
@days[i] = Day.new(hours_per_day, type)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
def to_h
|
|
24
|
+
{ start: { year: @start.year, month: @start.month, day: @start.day },
|
|
25
|
+
finish: { year: @finish.year, month: @finish.month, day: @finish.day },
|
|
26
|
+
days: (FIRST_DAY_OF_WEEK..LAST_DAY_OF_WEEK).map { |i| @days[i].to_h } }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.from_h(h)
|
|
30
|
+
s = h[:start]
|
|
31
|
+
f = h[:finish]
|
|
32
|
+
week = allocate
|
|
33
|
+
week.hours_per_day = HOURS_IN_DAY
|
|
34
|
+
week.start = Time.gm(s[:year], s[:month], s[:day])
|
|
35
|
+
week.finish = Time.gm(f[:year], f[:month], f[:day])
|
|
36
|
+
week.days = Array.new(LAST_DAY_OF_WEEK + 1)
|
|
37
|
+
h[:days].each_with_index { |dh, i| week.days[i] = Day.from_h(dh) }
|
|
38
|
+
week
|
|
39
|
+
end
|
|
40
|
+
|
|
23
41
|
def <=>(other)
|
|
24
42
|
return -1 if start < other.start
|
|
25
43
|
return 0 if start == other.start
|
|
@@ -27,7 +45,7 @@ module Workpattern
|
|
|
27
45
|
end
|
|
28
46
|
|
|
29
47
|
def week_total
|
|
30
|
-
elapsed_days > 6 ?
|
|
48
|
+
elapsed_days > 6 ? full_week_working_minutes : part_week_total_minutes
|
|
31
49
|
end
|
|
32
50
|
|
|
33
51
|
def total
|
|
@@ -36,56 +54,62 @@ module Workpattern
|
|
|
36
54
|
|
|
37
55
|
def workpattern(days, from_time, to_time, type)
|
|
38
56
|
DAYNAMES[days].each do |day|
|
|
39
|
-
if type ==
|
|
40
|
-
|
|
57
|
+
if type == WORK_TYPE
|
|
58
|
+
@days[day].set_working(from_time, to_time)
|
|
41
59
|
else
|
|
42
|
-
|
|
60
|
+
@days[day].set_resting(from_time, to_time)
|
|
43
61
|
end
|
|
44
62
|
end
|
|
45
63
|
end
|
|
46
64
|
|
|
47
65
|
def duplicate
|
|
48
|
-
duplicate_week = Week.new(start, finish)
|
|
49
|
-
|
|
66
|
+
duplicate_week = Week.new(@start, @finish)
|
|
67
|
+
FIRST_DAY_OF_WEEK.upto(LAST_DAY_OF_WEEK) do |i|
|
|
68
|
+
duplicate_week.days[i] = @days[i].clone
|
|
69
|
+
duplicate_week.days[i].hours_per_day = @days[i].hours_per_day
|
|
70
|
+
duplicate_week.days[i].pattern = @days[i].pattern
|
|
71
|
+
end
|
|
50
72
|
duplicate_week
|
|
51
73
|
end
|
|
52
74
|
|
|
53
|
-
def calc(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
75
|
+
def calc(a_date, a_duration, a_day = SAME_DAY)
|
|
76
|
+
if a_duration == 0
|
|
77
|
+
return a_date, a_duration
|
|
78
|
+
elsif a_duration > 0
|
|
79
|
+
return add(a_date, a_duration)
|
|
80
|
+
else
|
|
81
|
+
subtract(a_date, a_duration, a_day)
|
|
82
|
+
end
|
|
58
83
|
end
|
|
59
84
|
|
|
60
85
|
def working?(time)
|
|
61
|
-
|
|
62
|
-
false
|
|
86
|
+
@days[time.wday].working?(time.hour, time.min)
|
|
63
87
|
end
|
|
64
88
|
|
|
65
|
-
def resting?(
|
|
66
|
-
|
|
89
|
+
def resting?(time)
|
|
90
|
+
@days[time.wday].resting?(time.hour, time.min)
|
|
67
91
|
end
|
|
68
92
|
|
|
69
|
-
def diff(
|
|
70
|
-
|
|
93
|
+
def diff(start_date, finish_date)
|
|
94
|
+
if start_date > finish_date
|
|
95
|
+
start_date, finish_date = finish_date, start_date
|
|
96
|
+
end
|
|
71
97
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
98
|
+
if jd(start_date) == jd(finish_date)
|
|
99
|
+
return diff_in_same_day(start_date, finish_date)
|
|
100
|
+
else
|
|
101
|
+
return diff_in_same_weekpattern(start_date, finish_date)
|
|
102
|
+
end
|
|
75
103
|
end
|
|
76
|
-
|
|
104
|
+
|
|
77
105
|
private
|
|
78
106
|
|
|
79
|
-
def working_minutes_in(day)
|
|
80
|
-
day.to_s(2).count('1')
|
|
81
|
-
end
|
|
82
|
-
|
|
83
107
|
def elapsed_days
|
|
84
|
-
(finish - start).to_i /
|
|
108
|
+
(finish - start).to_i / DAY + 1
|
|
85
109
|
end
|
|
86
110
|
|
|
87
|
-
def
|
|
88
|
-
minutes_in_day_range
|
|
111
|
+
def full_week_working_minutes
|
|
112
|
+
minutes_in_day_range FIRST_DAY_OF_WEEK, LAST_DAY_OF_WEEK
|
|
89
113
|
end
|
|
90
114
|
|
|
91
115
|
def part_week_total_minutes
|
|
@@ -114,342 +138,155 @@ module Workpattern
|
|
|
114
138
|
end
|
|
115
139
|
|
|
116
140
|
def minutes_to_first_saturday
|
|
117
|
-
minutes_in_day_range(start.wday,
|
|
141
|
+
minutes_in_day_range(start.wday, LAST_DAY_OF_WEEK)
|
|
118
142
|
end
|
|
119
143
|
|
|
120
144
|
def minutes_to_finish_day
|
|
121
|
-
minutes_in_day_range(
|
|
145
|
+
minutes_in_day_range(FIRST_DAY_OF_WEEK, finish.wday)
|
|
122
146
|
end
|
|
123
147
|
|
|
124
148
|
def minutes_in_day_range(first, last)
|
|
125
|
-
@
|
|
149
|
+
@days[first..last].inject(0) { |sum, day| sum + day.working_minutes }
|
|
126
150
|
end
|
|
127
151
|
|
|
128
|
-
def add(
|
|
129
|
-
running_date, duration = add_to_end_of_day(initial_date, duration)
|
|
152
|
+
def add(a_date, a_duration)
|
|
130
153
|
|
|
131
|
-
|
|
132
|
-
running_date, duration = add_full_weeks running_date, duration
|
|
133
|
-
running_date, duration = add_remaining_days running_date, duration
|
|
134
|
-
[running_date, duration, false]
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def add_to_end_of_day(initial_date, duration)
|
|
138
|
-
available_minutes_in_day = minutes_to_end_of_day(initial_date)
|
|
154
|
+
r_date, r_duration = add_to_end_of_day(a_date, a_duration)
|
|
139
155
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
duration -= available_minutes_in_day
|
|
145
|
-
initial_date = end_of_this_day(initial_date)
|
|
146
|
-
else
|
|
147
|
-
initial_date = consume_minutes(initial_date, duration)
|
|
148
|
-
duration = 0
|
|
149
|
-
end
|
|
150
|
-
[initial_date, duration]
|
|
156
|
+
r_date, r_duration = add_to_finish_day r_date, r_duration
|
|
157
|
+
r_date, r_duration = add_full_weeks r_date, r_duration
|
|
158
|
+
r_date, r_duration = add_remaining_days r_date, r_duration
|
|
159
|
+
[r_date, r_duration, false]
|
|
151
160
|
end
|
|
152
161
|
|
|
153
|
-
def
|
|
154
|
-
|
|
155
|
-
date, duration = add_to_end_of_day(date, duration)
|
|
156
|
-
end
|
|
162
|
+
def add_to_end_of_day(a_date, a_duration)
|
|
163
|
+
r_date, r_duration, r_day = @days[a_date.wday].calc(a_date,a_duration)
|
|
157
164
|
|
|
158
|
-
|
|
159
|
-
|
|
165
|
+
if r_day == NEXT_DAY
|
|
166
|
+
r_date = start_of_next_day(r_date)
|
|
160
167
|
|
|
161
|
-
def add_full_weeks(date, duration)
|
|
162
|
-
while (duration != 0) && (duration >= week_total) && ((jd(date) + (6 * 86_400)) <= jd(finish))
|
|
163
|
-
duration -= week_total
|
|
164
|
-
date += (7 * 86_400)
|
|
165
168
|
end
|
|
166
169
|
|
|
167
|
-
[
|
|
170
|
+
[r_date, r_duration]
|
|
168
171
|
end
|
|
169
172
|
|
|
170
|
-
def
|
|
171
|
-
while (
|
|
172
|
-
|
|
173
|
-
end
|
|
174
|
-
[date, duration]
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def add_to_finish_day(date, duration)
|
|
178
|
-
while ( duration != 0) && (date.wday != next_day(self.finish).wday) && (jd(date) <= jd(self.finish))
|
|
179
|
-
date, duration = add_to_end_of_day(date,duration)
|
|
173
|
+
def add_to_finish_day(a_date, a_duration)
|
|
174
|
+
while ( a_duration != 0) && (a_date.wday != next_day(self.finish).wday) && (jd(a_date) <= jd(self.finish))
|
|
175
|
+
a_date, a_duration = add_to_end_of_day(a_date,a_duration)
|
|
180
176
|
end
|
|
181
177
|
|
|
182
|
-
|
|
178
|
+
[a_date, a_duration]
|
|
183
179
|
end
|
|
184
180
|
|
|
185
|
-
def add_full_weeks(
|
|
181
|
+
def add_full_weeks(a_date, a_duration)
|
|
186
182
|
|
|
187
|
-
while (
|
|
188
|
-
|
|
189
|
-
|
|
183
|
+
while (a_duration != 0) && (a_duration >= self.week_total) && ((jd(a_date) + (6*86400)) <= jd(self.finish))
|
|
184
|
+
a_duration -= self.week_total
|
|
185
|
+
a_date += (7*86400)
|
|
190
186
|
end
|
|
191
187
|
|
|
192
|
-
|
|
188
|
+
[a_date, a_duration]
|
|
193
189
|
end
|
|
194
190
|
|
|
195
|
-
def add_remaining_days(
|
|
196
|
-
while (
|
|
197
|
-
|
|
191
|
+
def add_remaining_days(a_date, a_duration)
|
|
192
|
+
while (a_duration != 0) && (jd(a_date) <= jd(self.finish))
|
|
193
|
+
a_date, a_duration = add_to_end_of_day(a_date,a_duration)
|
|
198
194
|
end
|
|
199
|
-
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def work_on_day(day,from_time,to_time)
|
|
203
|
-
self.values[day] = self.values[day] | time_mask(from_time, to_time)
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
def rest_on_day(day,from_time,to_time)
|
|
207
|
-
mask_of_1s = time_mask(from_time, to_time)
|
|
208
|
-
mask = mask_of_1s ^ working_day & working_day
|
|
209
|
-
self.values[day] = self.values[day] & mask
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
def time_mask(from_time, to_time)
|
|
213
|
-
bit_pos(to_time.hour, to_time.min + 1) - bit_pos(from_time.hour, from_time.min)
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
def bit_pos(hour,minute)
|
|
217
|
-
2**( (hour * 60) + minute )
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
def work_on_day(day, from_time, to_time)
|
|
221
|
-
values[day] = values[day] | time_mask(from_time, to_time)
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
def rest_on_day(day, from_time, to_time)
|
|
225
|
-
mask_of_ones = time_mask(from_time, to_time)
|
|
226
|
-
mask = mask_of_ones ^ working_day & working_day
|
|
227
|
-
values[day] = values[day] & mask
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
def time_mask(from_time, to_time)
|
|
231
|
-
bit_pos(to_time.hour, to_time.min + 1) - bit_pos(from_time.hour, from_time.min)
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
def bit_pos(hour, minute)
|
|
235
|
-
2**((hour * 60) + minute)
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
def minutes_to_end_of_day(date)
|
|
239
|
-
working_minutes_in pattern_to_end_of_day(date)
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
def pattern_to_end_of_day(date)
|
|
243
|
-
mask = mask_to_end_of_day(date)
|
|
244
|
-
(values[date.wday] & mask)
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
def mask_to_end_of_day(date)
|
|
248
|
-
bit_pos(hours_per_day, 0) - bit_pos(date.hour, date.min)
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
def working_day
|
|
252
|
-
2**(60 * hours_per_day) - 1
|
|
195
|
+
[a_date, a_duration]
|
|
253
196
|
end
|
|
254
197
|
|
|
255
198
|
def start_of_next_day(date)
|
|
256
199
|
next_day(date) - (HOUR * date.hour) - (MINUTE * date.min)
|
|
257
200
|
end
|
|
258
201
|
|
|
259
|
-
def
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
def start_of_today(date)
|
|
264
|
-
start_of_next_day(prev_day(date))
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
def end_of_this_day(date)
|
|
268
|
-
position = pattern_to_end_of_day(date).to_s(2).size
|
|
269
|
-
adjust_date(date, position)
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
def adjust_date(date, adjustment)
|
|
273
|
-
date - (HOUR * date.hour) - (MINUTE * date.min) + (MINUTE * adjustment)
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
def mask_to_start_of_day(date)
|
|
277
|
-
bit_pos(date.hour, date.min) - bit_pos(0, 0)
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
def pattern_to_start_of_day(date)
|
|
281
|
-
mask = mask_to_start_of_day(date)
|
|
282
|
-
(values[date.wday] & mask)
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
def minutes_to_start_of_day(date)
|
|
286
|
-
working_minutes_in pattern_to_start_of_day(date)
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
def consume_minutes(date, duration)
|
|
290
|
-
minutes = pattern_to_end_of_day(date).to_s(2).reverse! if duration > 0
|
|
291
|
-
minutes = pattern_to_start_of_day(date).to_s(2) if duration < 0
|
|
292
|
-
|
|
293
|
-
top = minutes.size
|
|
294
|
-
bottom = 1
|
|
295
|
-
mark = top / 2
|
|
296
|
-
|
|
297
|
-
while minutes[0, mark].count('1') != duration.abs
|
|
298
|
-
last_mark = mark
|
|
299
|
-
if minutes[0, mark].count('1') < duration.abs
|
|
300
|
-
|
|
301
|
-
bottom = mark
|
|
302
|
-
mark = (top - mark) / 2 + mark
|
|
303
|
-
mark = top if last_mark == mark
|
|
304
|
-
|
|
305
|
-
else
|
|
306
|
-
|
|
307
|
-
top = mark
|
|
308
|
-
mark = (mark - bottom) / 2 + bottom
|
|
309
|
-
mark = bottom if last_mark == mark
|
|
310
|
-
|
|
311
|
-
end
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
mark = minutes_addition_adjustment(minutes, mark) if duration > 0
|
|
315
|
-
mark = minutes_subtraction_adjustment(minutes, mark) if duration < 0
|
|
316
|
-
|
|
317
|
-
return adjust_date(date, mark) if duration > 0
|
|
318
|
-
return start_of_today(date) + (MINUTE * mark) if duration < 0
|
|
319
|
-
end
|
|
202
|
+
def subtract_to_start_of_day(a_date, a_duration, a_day)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
a_date, a_duration, a_day = handle_midnight(a_date, a_duration, a_day)
|
|
320
206
|
|
|
321
|
-
|
|
322
|
-
i = mark - 1
|
|
207
|
+
r_date, r_duration, r_day = @days[a_date.wday].calc(a_date, a_duration)
|
|
323
208
|
|
|
324
|
-
|
|
325
|
-
i -= 1
|
|
326
|
-
end
|
|
209
|
+
[r_date, r_duration, r_day]
|
|
327
210
|
|
|
328
|
-
minutes.size - (i + 1)
|
|
329
211
|
end
|
|
330
212
|
|
|
331
|
-
def
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
minutes.size
|
|
339
|
-
end
|
|
340
|
-
|
|
341
|
-
def subtract_to_start_of_day(initial_date, duration, midnight)
|
|
342
|
-
initial_date, duration, midnight = handle_midnight(initial_date, duration) if midnight
|
|
343
|
-
available_minutes_in_day = minutes_to_start_of_day(initial_date)
|
|
344
|
-
|
|
345
|
-
if duration != 0
|
|
346
|
-
if available_minutes_in_day < duration.abs
|
|
347
|
-
duration += available_minutes_in_day
|
|
348
|
-
initial_date = start_of_previous_day(initial_date)
|
|
349
|
-
midnight = true
|
|
350
|
-
else
|
|
351
|
-
initial_date = consume_minutes(initial_date, duration)
|
|
352
|
-
duration = 0
|
|
353
|
-
midnight = false
|
|
354
|
-
end
|
|
355
|
-
end
|
|
356
|
-
[initial_date, duration, midnight]
|
|
357
|
-
end
|
|
213
|
+
def handle_midnight(a_date, a_duration, a_day)
|
|
214
|
+
|
|
215
|
+
if a_day == PREVIOUS_DAY
|
|
216
|
+
a_date -= DAY
|
|
217
|
+
a_date = Time.gm(a_date.year, a_date.month, a_date.day,LAST_TIME_IN_DAY.hour, LAST_TIME_IN_DAY.min)
|
|
358
218
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
219
|
+
if @days[a_date.wday].working?(a_date.hour, a_date.min)
|
|
220
|
+
a_duration += 1
|
|
221
|
+
end
|
|
362
222
|
end
|
|
363
223
|
|
|
364
|
-
|
|
365
|
-
initial_date -= (MINUTE * initial_date.min)
|
|
366
|
-
initial_date = next_day(initial_date) - MINUTE
|
|
367
|
-
|
|
368
|
-
[initial_date, duration, false]
|
|
224
|
+
[a_date, a_duration, SAME_DAY]
|
|
369
225
|
end
|
|
370
226
|
|
|
371
|
-
def subtract(
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
227
|
+
def subtract(a_date, a_duration, a_day)
|
|
228
|
+
a_date, a_duration, a_day = handle_midnight(a_date, a_duration, a_day)
|
|
229
|
+
a_date, a_duration, a_day = subtract_to_start_of_day(a_date, a_duration, a_day)
|
|
230
|
+
|
|
231
|
+
while (a_duration != 0) && (a_date.wday != start.wday) && (jd(a_date) > jd(start))
|
|
232
|
+
a_date, a_duration, a_day = handle_midnight(a_date, a_duration, a_day)
|
|
233
|
+
a_date, a_duration, a_day = subtract_to_start_of_day(a_date, a_duration, a_day)
|
|
378
234
|
end
|
|
379
235
|
|
|
380
|
-
while (
|
|
381
|
-
|
|
382
|
-
|
|
236
|
+
while (a_duration != 0) && (a_duration >= week_total) && ((jd(a_date) - (6 * DAY)) >= jd(start))
|
|
237
|
+
a_duration += week_total
|
|
238
|
+
a_date -= 7
|
|
383
239
|
end
|
|
384
240
|
|
|
385
|
-
while (
|
|
386
|
-
|
|
387
|
-
duration,
|
|
388
|
-
midnight)
|
|
241
|
+
while (a_duration != 0) && (jd(a_date) > jd(start))
|
|
242
|
+
a_date, a_duration, a_day = subtract_to_start_of_day(a_date,a_duration,a_day)
|
|
389
243
|
end
|
|
390
244
|
|
|
391
|
-
[
|
|
245
|
+
[a_date, a_duration, a_day]
|
|
392
246
|
end
|
|
393
247
|
|
|
394
248
|
def diff_in_same_weekpattern(start_date, finish_date)
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
duration += minutes_to_end_of_day(start_date)
|
|
401
|
-
start_date = start_of_next_day(start_date)
|
|
249
|
+
minutes = @days[start_date.wday].working_minutes(start_date, LAST_TIME_IN_DAY)
|
|
250
|
+
run_date = start_of_next_day(start_date)
|
|
251
|
+
while (run_date.wday != start.wday) && (jd(run_date) < jd(finish)) && (jd(run_date) != jd(finish_date))
|
|
252
|
+
minutes += @days[run_date.wday].working_minutes
|
|
253
|
+
run_date += DAY
|
|
402
254
|
end
|
|
403
255
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
duration += week_total
|
|
408
|
-
start_date += (7 * 86_400)
|
|
256
|
+
while ((jd(run_date) + (7 * DAY)) < jd(finish_date)) && ((jd(run_date) + (7 * DAY)) < jd(finish))
|
|
257
|
+
minutes += week_total
|
|
258
|
+
run_date += (7 * DAY)
|
|
409
259
|
end
|
|
410
260
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
duration += minutes_to_end_of_day(start_date)
|
|
415
|
-
start_date = start_of_next_day(start_date)
|
|
261
|
+
while (jd(run_date) < jd(finish_date)) && (jd(run_date) <= jd(finish))
|
|
262
|
+
minutes += @days[run_date.wday].working_minutes
|
|
263
|
+
run_date += DAY
|
|
416
264
|
end
|
|
417
265
|
|
|
418
|
-
if
|
|
419
|
-
|
|
266
|
+
if run_date != finish_date
|
|
267
|
+
|
|
268
|
+
if (jd(run_date) == jd(finish_date)) && (jd(run_date) <= jd(finish))
|
|
269
|
+
minutes += @days[run_date.wday].working_minutes(run_date, finish_date - MINUTE)
|
|
270
|
+
run_date = finish_date
|
|
271
|
+
elsif (jd(run_date) <= jd(finish))
|
|
272
|
+
minutes += @days[run_date.wday].working_minutes
|
|
273
|
+
run_date += DAY
|
|
274
|
+
end
|
|
420
275
|
end
|
|
421
|
-
duration += interim_duration unless interim_duration.nil?
|
|
422
|
-
[duration, start_date]
|
|
423
|
-
end
|
|
424
276
|
|
|
425
|
-
|
|
426
|
-
duration, start_date = diff_in_same_weekpattern(start_date, finish_date)
|
|
427
|
-
[duration, start_date]
|
|
428
|
-
end
|
|
277
|
+
[minutes, run_date]
|
|
429
278
|
|
|
430
|
-
def diff_to_tomorrow(start_date)
|
|
431
|
-
finish_bit_pos = bit_pos(hours_per_day, 0)
|
|
432
|
-
start_bit_pos = bit_pos(start_date.hour, start_date.min)
|
|
433
|
-
mask = finish_bit_pos - start_bit_pos
|
|
434
|
-
minutes = working_minutes_in(values[start_date.wday] & mask)
|
|
435
|
-
[minutes, start_of_next_day(start_date)]
|
|
436
279
|
end
|
|
437
280
|
|
|
438
281
|
def diff_in_same_day(start_date, finish_date)
|
|
439
|
-
|
|
440
|
-
start_bit_pos = bit_pos(start_date.hour, start_date.min)
|
|
441
|
-
mask = finish_bit_pos - start_bit_pos
|
|
442
|
-
minutes = working_minutes_in(values[start_date.wday] & mask)
|
|
282
|
+
minutes = @days[start_date.wday].working_minutes(start_date, finish_date - MINUTE)
|
|
443
283
|
[minutes, finish_date]
|
|
444
284
|
end
|
|
445
285
|
|
|
446
286
|
def next_day(time)
|
|
447
|
-
time +
|
|
287
|
+
time + DAY
|
|
448
288
|
end
|
|
449
289
|
|
|
450
|
-
def prev_day(time)
|
|
451
|
-
time - 86_400
|
|
452
|
-
end
|
|
453
290
|
|
|
454
291
|
def jd(time)
|
|
455
292
|
Time.gm(time.year, time.month, time.day)
|