workpattern 0.3.6 → 0.4.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 +13 -5
- data/.travis.yml +4 -1
- data/CHANGELOG +5 -0
- data/lib/workpattern.rb +0 -2
- data/lib/workpattern/version.rb +1 -3
- data/lib/workpattern/week.rb +307 -311
- data/lib/workpattern/workpattern.rb +7 -2
- data/test/test_week.rb +95 -23
- metadata +8 -12
- data/lib/workpattern/day.rb +0 -343
- data/lib/workpattern/hour.rb +0 -206
- data/test/test_day.rb +0 -558
- data/test/test_hour.rb +0 -396
@@ -277,8 +277,8 @@ module Workpattern
|
|
277
277
|
#
|
278
278
|
def clone_and_adjust_current_wp(current_wp, current_start,current_finish,clone_start,clone_finish=nil)
|
279
279
|
clone_wp=current_wp.duplicate
|
280
|
-
current_wp
|
281
|
-
clone_finish.nil? ? clone_wp
|
280
|
+
adjust_date_range(current_wp,current_start,current_finish)
|
281
|
+
clone_finish.nil? ? adjust_date_range(clone_wp,clone_start,clone_wp.finish) : adjust_date_range(clone_wp, clone_start,clone_finish)
|
282
282
|
return clone_wp
|
283
283
|
end
|
284
284
|
|
@@ -286,6 +286,11 @@ module Workpattern
|
|
286
286
|
new_wp.workpattern(args[:days],args[:from_time],args[:to_time],args[:work_type])
|
287
287
|
weeks<< new_wp
|
288
288
|
end
|
289
|
+
|
290
|
+
def adjust_date_range(week_pattern,start_date,finish_date)
|
291
|
+
week_pattern.start = start_date
|
292
|
+
week_pattern.finish = finish_date
|
293
|
+
end
|
289
294
|
end
|
290
295
|
end
|
291
296
|
|
data/test/test_week.rb
CHANGED
@@ -5,6 +5,7 @@ class TestWeek < MiniTest::Unit::TestCase #:nodoc:
|
|
5
5
|
def setup
|
6
6
|
start=DateTime.new(2000,1,3)
|
7
7
|
finish=DateTime.new(2000,1,9)
|
8
|
+
|
8
9
|
@working_week=Workpattern::Week.new(start,finish,1)
|
9
10
|
|
10
11
|
@resting_week=Workpattern::Week.new(start,finish,0)
|
@@ -14,33 +15,46 @@ class TestWeek < MiniTest::Unit::TestCase #:nodoc:
|
|
14
15
|
@pattern_week.workpattern(:weekday,Workpattern.clock(0,0),Workpattern.clock(8,59),0)
|
15
16
|
@pattern_week.workpattern(:weekday,Workpattern.clock(12,30),Workpattern.clock(13,0),0)
|
16
17
|
@pattern_week.workpattern(:weekday,Workpattern.clock(17,0),Workpattern.clock(23,59),0)
|
17
|
-
|
18
|
+
|
18
19
|
end
|
19
20
|
|
20
|
-
def test_must_diff_from_last_day_of_patterned_week
|
21
|
-
#issue 15
|
22
|
-
start=DateTime.new(2013,9,23,0,0)
|
23
|
-
finish=DateTime.new(2013,9,26,23,59)
|
24
|
-
working_week=week(start,finish,1)
|
25
|
-
working_week.workpattern :all, Workpattern.clock(0,0),Workpattern.clock(8,59),0
|
26
|
-
working_week.workpattern :all, Workpattern.clock(12,0),Workpattern.clock(12,59),0
|
27
|
-
working_week.workpattern :all, Workpattern.clock(18,0),Workpattern.clock(23,59),0
|
28
21
|
|
29
|
-
duration, start =working_week.diff(DateTime.civil(2013,9,26,17,0),DateTime.civil(2013,9,27,10,0))
|
30
|
-
|
31
|
-
assert_equal 60, duration
|
32
|
-
assert_equal DateTime.civil(2013,9,27,0,0), start
|
33
|
-
end
|
34
|
-
|
35
22
|
def test_must_create_a_working_week
|
36
23
|
start=DateTime.new(2000,1,1,11,3)
|
37
24
|
finish=DateTime.new(2005,12,31,16,41)
|
38
25
|
working_week=week(start,finish,1)
|
39
26
|
assert_equal DateTime.new(start.year,start.month,start.day), working_week.start
|
40
27
|
assert_equal DateTime.new(finish.year,finish.month,finish.day), working_week.finish
|
41
|
-
assert_equal 3156480, working_week.total#2192
|
28
|
+
assert_equal 3156480, working_week.total #2192 days
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_create_working_week_of_3_concecutive_days
|
32
|
+
start=DateTime.new(2000,1,2,11,3) # Sunday
|
33
|
+
finish=DateTime.new(2000,1,4,16,41) # Tuesday
|
34
|
+
working_week=week(start,finish,1)
|
35
|
+
assert_equal DateTime.new(start.year,start.month,start.day), working_week.start
|
36
|
+
assert_equal DateTime.new(finish.year,finish.month,finish.day), working_week.finish
|
37
|
+
assert_equal 1440 * 3, working_week.total #3 days
|
42
38
|
end
|
43
|
-
|
39
|
+
|
40
|
+
def test_create_working_week_f_to_Su
|
41
|
+
start=DateTime.new(2000,1,7,11,3) # Friday
|
42
|
+
finish=DateTime.new(2000,1,9,16,41) # Sunday
|
43
|
+
working_week=week(start,finish,1)
|
44
|
+
assert_equal DateTime.new(start.year,start.month,start.day), working_week.start
|
45
|
+
assert_equal DateTime.new(finish.year,finish.month,finish.day), working_week.finish
|
46
|
+
assert_equal 1440 * 3, working_week.total #3 days
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_create_working_week_Th_to_Su
|
50
|
+
start=DateTime.new(2000,1,6,11,3) # Thursday
|
51
|
+
finish=DateTime.new(2000,1,8,16,41) # Sunday
|
52
|
+
working_week=week(start,finish,1)
|
53
|
+
assert_equal DateTime.new(start.year,start.month,start.day), working_week.start
|
54
|
+
assert_equal DateTime.new(finish.year,finish.month,finish.day), working_week.finish
|
55
|
+
assert_equal 1440 * 3, working_week.total #3 days
|
56
|
+
end
|
57
|
+
|
44
58
|
def test_must_create_a_resting_week
|
45
59
|
start=DateTime.new(2000,1,1,11,3)
|
46
60
|
finish=DateTime.new(2005,12,31,16,41)
|
@@ -50,7 +64,7 @@ class TestWeek < MiniTest::Unit::TestCase #:nodoc:
|
|
50
64
|
assert_equal 0, resting_week.total#2192
|
51
65
|
assert_equal 0,resting_week.week_total
|
52
66
|
end
|
53
|
-
|
67
|
+
|
54
68
|
def test_must_duplicate_all_of_a_week
|
55
69
|
start=DateTime.new(2000,1,1,11,3)
|
56
70
|
finish=DateTime.new(2005,12,31,16,41)
|
@@ -59,7 +73,8 @@ class TestWeek < MiniTest::Unit::TestCase #:nodoc:
|
|
59
73
|
assert_equal DateTime.new(start.year,start.month,start.day), new_week.start
|
60
74
|
assert_equal DateTime.new(finish.year,finish.month,finish.day), new_week.finish
|
61
75
|
assert_equal 3156480, new_week.total#2192
|
62
|
-
|
76
|
+
week.workpattern(:weekend,Workpattern.clock(0,0),Workpattern.clock(23,59),0)
|
77
|
+
assert_equal 3156480, new_week.total#2192
|
63
78
|
end
|
64
79
|
|
65
80
|
def test_must_set_week_pattern_correctly
|
@@ -79,7 +94,7 @@ class TestWeek < MiniTest::Unit::TestCase #:nodoc:
|
|
79
94
|
pattern_week.workpattern(:weekday,Workpattern.clock(17,0),Workpattern.clock(23,59),0)
|
80
95
|
assert_equal 2245, pattern_week.week_total
|
81
96
|
end
|
82
|
-
|
97
|
+
|
83
98
|
def test_must_set_patterns_correctly
|
84
99
|
start=DateTime.new(2000,1,1,0,0)
|
85
100
|
finish=DateTime.new(2005,12,31,8,59)
|
@@ -203,7 +218,7 @@ class TestWeek < MiniTest::Unit::TestCase #:nodoc:
|
|
203
218
|
assert_equal 0, result_duration
|
204
219
|
end
|
205
220
|
|
206
|
-
def
|
221
|
+
def test_must_add_minutes_from_working_in_a_pattern_week_result_in_later_day
|
207
222
|
result_date, result_duration, midnight_flag = @pattern_week.calc(DateTime.new(2000,1,3,10,11),828)
|
208
223
|
assert_equal DateTime.new(2000,1,5,9,1), result_date
|
209
224
|
refute midnight_flag
|
@@ -397,7 +412,20 @@ class TestWeek < MiniTest::Unit::TestCase #:nodoc:
|
|
397
412
|
|
398
413
|
### @pattern_week centric
|
399
414
|
|
400
|
-
|
415
|
+
def must_diff_day_week_day_in_patterned_week
|
416
|
+
start=DateTime.new(2013,9,23,0,0)
|
417
|
+
finish=DateTime.new(2013,10,20,23,59)
|
418
|
+
working_week=week(start,finish,1)
|
419
|
+
working_week.workpattern :all, Workpattern.clock(0,0),Workpattern.clock(8,59),0
|
420
|
+
working_week.workpattern :all, Workpattern.clock(12,0),Workpattern.clock(12,59),0
|
421
|
+
working_week.workpattern :all, Workpattern.clock(18,0),Workpattern.clock(23,59),0
|
422
|
+
|
423
|
+
duration, start =working_week.diff(DateTime.civil(2013,10,3,16,0),DateTime.civil(2013,10,15,12,30))
|
424
|
+
|
425
|
+
assert_equal 5640, duration
|
426
|
+
assert_equal DateTime.civil(2013,10,15,12,30), start
|
427
|
+
|
428
|
+
end
|
401
429
|
def test_must_calculate_difference_between_dates_in_working_week
|
402
430
|
late_date=DateTime.new(2000,1,6,9,32)
|
403
431
|
early_date=DateTime.new(2000,1,6,8,20)
|
@@ -421,6 +449,51 @@ class TestWeek < MiniTest::Unit::TestCase #:nodoc:
|
|
421
449
|
assert_equal 1, result_dur
|
422
450
|
assert_equal late_date, result_date
|
423
451
|
end
|
452
|
+
|
453
|
+
def test_must_diff_from_last_day_of_patterned_week
|
454
|
+
#issue 15
|
455
|
+
start=DateTime.new(2013,9,23,0,0)
|
456
|
+
finish=DateTime.new(2013,9,26,23,59)
|
457
|
+
working_week=week(start,finish,1)
|
458
|
+
working_week.workpattern :all, Workpattern.clock(0,0),Workpattern.clock(8,59),0
|
459
|
+
working_week.workpattern :all, Workpattern.clock(12,0),Workpattern.clock(12,59),0
|
460
|
+
working_week.workpattern :all, Workpattern.clock(18,0),Workpattern.clock(23,59),0
|
461
|
+
|
462
|
+
duration, start =working_week.diff(DateTime.civil(2013,9,26,17,0),DateTime.civil(2013,9,27,10,0))
|
463
|
+
|
464
|
+
assert_equal 60, duration
|
465
|
+
assert_equal DateTime.civil(2013,9,27,0,0), start
|
466
|
+
end
|
467
|
+
|
468
|
+
def test_must_diff_long_distances_beyond_end_of_patterned_week
|
469
|
+
start=DateTime.new(2013,9,23,0,0)
|
470
|
+
finish=DateTime.new(2013,10,20,23,59)
|
471
|
+
working_week=week(start,finish,1)
|
472
|
+
working_week.workpattern :all, Workpattern.clock(0,0),Workpattern.clock(8,59),0
|
473
|
+
working_week.workpattern :all, Workpattern.clock(12,0),Workpattern.clock(12,59),0
|
474
|
+
working_week.workpattern :all, Workpattern.clock(18,0),Workpattern.clock(23,59),0
|
475
|
+
|
476
|
+
duration, start =working_week.diff(DateTime.civil(2013,9,26,17,0),DateTime.civil(2018,9,27,10,0))
|
477
|
+
|
478
|
+
assert_equal 11580, duration
|
479
|
+
assert_equal DateTime.civil(2013,10,21,0,0), start
|
480
|
+
|
481
|
+
end
|
482
|
+
|
483
|
+
def test_must_diff_long_distances_within_patterned_week
|
484
|
+
start=DateTime.new(2013,9,23,0,0)
|
485
|
+
finish=DateTime.new(2013,10,20,23,59)
|
486
|
+
working_week=week(start,finish,1)
|
487
|
+
working_week.workpattern :all, Workpattern.clock(0,0),Workpattern.clock(8,59),0
|
488
|
+
working_week.workpattern :all, Workpattern.clock(12,0),Workpattern.clock(12,59),0
|
489
|
+
working_week.workpattern :all, Workpattern.clock(18,0),Workpattern.clock(23,59),0
|
490
|
+
|
491
|
+
duration, start =working_week.diff(DateTime.civil(2013,9,26,17,0),DateTime.civil(2013,10,15,10,0))
|
492
|
+
|
493
|
+
assert_equal 8760, duration
|
494
|
+
assert_equal DateTime.civil(2013,10,15,10,0), start
|
495
|
+
|
496
|
+
end
|
424
497
|
|
425
498
|
private
|
426
499
|
|
@@ -432,4 +505,3 @@ class TestWeek < MiniTest::Unit::TestCase #:nodoc:
|
|
432
505
|
return Workpattern.clock(hour,min)
|
433
506
|
end
|
434
507
|
end
|
435
|
-
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: workpattern
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.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: 2014-
|
11
|
+
date: 2014-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.9.2
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.9.2
|
27
27
|
description: Workpattern performs date calculations that take into account working
|
@@ -32,8 +32,8 @@ executables: []
|
|
32
32
|
extensions: []
|
33
33
|
extra_rdoc_files: []
|
34
34
|
files:
|
35
|
-
-
|
36
|
-
-
|
35
|
+
- .gitignore
|
36
|
+
- .travis.yml
|
37
37
|
- CHANGELOG
|
38
38
|
- Gemfile
|
39
39
|
- README.md
|
@@ -41,8 +41,6 @@ files:
|
|
41
41
|
- config/website.yml
|
42
42
|
- lib/workpattern.rb
|
43
43
|
- lib/workpattern/clock.rb
|
44
|
-
- lib/workpattern/day.rb
|
45
|
-
- lib/workpattern/hour.rb
|
46
44
|
- lib/workpattern/utility/base.rb
|
47
45
|
- lib/workpattern/version.rb
|
48
46
|
- lib/workpattern/week.rb
|
@@ -52,9 +50,7 @@ files:
|
|
52
50
|
- script/generate
|
53
51
|
- script/txt2html
|
54
52
|
- test/test_clock.rb
|
55
|
-
- test/test_day.rb
|
56
53
|
- test/test_helper.rb
|
57
|
-
- test/test_hour.rb
|
58
54
|
- test/test_week.rb
|
59
55
|
- test/test_workpattern.rb
|
60
56
|
- test/test_workpattern_module.rb
|
@@ -69,12 +65,12 @@ require_paths:
|
|
69
65
|
- lib
|
70
66
|
required_ruby_version: !ruby/object:Gem::Requirement
|
71
67
|
requirements:
|
72
|
-
- -
|
68
|
+
- - ! '>='
|
73
69
|
- !ruby/object:Gem::Version
|
74
70
|
version: '0'
|
75
71
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
72
|
requirements:
|
77
|
-
- -
|
73
|
+
- - ! '>='
|
78
74
|
- !ruby/object:Gem::Version
|
79
75
|
version: '0'
|
80
76
|
requirements: []
|
data/lib/workpattern/day.rb
DELETED
@@ -1,343 +0,0 @@
|
|
1
|
-
module Workpattern
|
2
|
-
|
3
|
-
# @author Barrie Callender
|
4
|
-
# @!attribute values
|
5
|
-
# @return [Array] each hour of the day
|
6
|
-
# @!attribute hours
|
7
|
-
# @return [Integer] number of hours in the day
|
8
|
-
# @!attribute first_hour
|
9
|
-
# @return [Integer] first working hour in the day
|
10
|
-
# @!attribute first_min
|
11
|
-
# @return [Integer] first working minute in first working hour in the day
|
12
|
-
# @!attribute last_hour
|
13
|
-
# @return [Integer] last working hour in the day
|
14
|
-
# @!attribute last_min
|
15
|
-
# @return [Integer] last working minute in last working hour in the day
|
16
|
-
# @!attribute total
|
17
|
-
# @return [Integer] total number of minutes in the day
|
18
|
-
#
|
19
|
-
# Represents the 24 hours of a day.
|
20
|
-
#
|
21
|
-
# @since 0.2.0
|
22
|
-
# @todo implement a day with different number of hours in it to support daylight saving
|
23
|
-
#
|
24
|
-
class Day
|
25
|
-
include Workpattern::Utility
|
26
|
-
attr_accessor :values, :hours, :first_hour, :first_min, :last_hour, :last_min, :total
|
27
|
-
|
28
|
-
# The new <tt>Day</tt> object can be created as either working or resting.
|
29
|
-
#
|
30
|
-
# @param [Integer] type is working (1) or resting (0)
|
31
|
-
#
|
32
|
-
def initialize(type=1)
|
33
|
-
@hours=24
|
34
|
-
hour=WORKING_HOUR if type==1
|
35
|
-
hour=RESTING_HOUR if type==0
|
36
|
-
@values=Array.new(@hours) {|index| hour }
|
37
|
-
end
|
38
|
-
|
39
|
-
# Creates a duplicate of the current <tt>Day</tt> instance.
|
40
|
-
#
|
41
|
-
# @return [Day]
|
42
|
-
#
|
43
|
-
def duplicate
|
44
|
-
duplicate_day = Day.new()
|
45
|
-
duplicate_values=Array.new(self.values.size)
|
46
|
-
self.values.each_index {|index|
|
47
|
-
duplicate_values[index]=self.values[index]
|
48
|
-
}
|
49
|
-
duplicate_day.values=duplicate_values
|
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
|
56
|
-
duplicate_day.refresh
|
57
|
-
return duplicate_day
|
58
|
-
end
|
59
|
-
|
60
|
-
# Recalculates characteristics for this day
|
61
|
-
# no longer required as calculating individually is faster
|
62
|
-
#
|
63
|
-
def refresh
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
# Sets all minutes in a date range to be working or resting.
|
68
|
-
#
|
69
|
-
# @param [(#hour,#min)] start_time is the start of the range to set
|
70
|
-
# @param [(#hour, #min)] finish_time is the finish of the range to be set
|
71
|
-
# @param [Integer] type is either working (1) or resting (0)
|
72
|
-
#
|
73
|
-
def workpattern(start_time,finish_time,type)
|
74
|
-
|
75
|
-
if start_time.hour==finish_time.hour
|
76
|
-
self.values[start_time.hour]=self.values[start_time.hour].wp_workpattern(start_time.min,finish_time.min,type)
|
77
|
-
else
|
78
|
-
test_hour=start_time.hour
|
79
|
-
self.values[test_hour]=self.values[test_hour].wp_workpattern(start_time.min,59,type)
|
80
|
-
|
81
|
-
while ((test_hour+1)<finish_time.hour)
|
82
|
-
test_hour+=1
|
83
|
-
self.values[test_hour]=self.values[test_hour].wp_workpattern(0,59,type)
|
84
|
-
end
|
85
|
-
|
86
|
-
self.values[finish_time.hour]=self.values[finish_time.hour].wp_workpattern(0,finish_time.min,type)
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
90
|
-
|
91
|
-
# Calculates the result of adding <tt>duration</tt> to
|
92
|
-
# <tt>time</tt>. The <tt>duration</tt> can be negative in
|
93
|
-
# which case it subtracts from <tt>time</tt>.
|
94
|
-
#
|
95
|
-
# An addition where there are less working minutes left in
|
96
|
-
# the day than are being added will result in the time
|
97
|
-
# returned being 00:00 on the following day.
|
98
|
-
#
|
99
|
-
# A subtraction where there are less working minutes left in
|
100
|
-
# the day than are being added will result in the time
|
101
|
-
# returned being the previous day with the <tt>midnight</tt> flag set to true.
|
102
|
-
#
|
103
|
-
# @param [DateTime] time when the calculation starts from
|
104
|
-
# @param [Integer] duration is the number of minutes to add or subtract if it is negative
|
105
|
-
# @param [Boolean] midnight is a flag used in subtraction to pretend the time is actually midnight
|
106
|
-
# @return [DateTime,Integer,Boolean] Calculated time along with any remaining duration and the midnight flag
|
107
|
-
#
|
108
|
-
def calc(time,duration,midnight=false)
|
109
|
-
|
110
|
-
if (duration<0)
|
111
|
-
return subtract(time,duration, midnight)
|
112
|
-
elsif (duration>0)
|
113
|
-
return add(time,duration)
|
114
|
-
else
|
115
|
-
return time,duration, false
|
116
|
-
end
|
117
|
-
|
118
|
-
end
|
119
|
-
|
120
|
-
# Returns true if the given minute is working and false if it is resting
|
121
|
-
#
|
122
|
-
# @param [(#hour, #min)] start is the time in the day to inspect
|
123
|
-
# @return [Boolean] true if the time is working and false if it is resting
|
124
|
-
#
|
125
|
-
def working?(start)
|
126
|
-
return true if minutes(start.hour,start.min,start.hour,start.min)==1
|
127
|
-
return false
|
128
|
-
end
|
129
|
-
|
130
|
-
# Returns the difference in working minutes between two times.
|
131
|
-
#
|
132
|
-
# @param [(#hour, #min)] start start time in the range
|
133
|
-
# @param [(#hour, #min)] finish finish time in the range
|
134
|
-
# @return [Integer] number of working minutes
|
135
|
-
#
|
136
|
-
def diff(start,finish)
|
137
|
-
start,finish=finish,start if ((start <=> finish))==1
|
138
|
-
# calculate to end of hour
|
139
|
-
#
|
140
|
-
if (start.jd==finish.jd) # same day
|
141
|
-
duration=minutes(start.hour,start.min,finish.hour, finish.min)
|
142
|
-
duration -=1 if working?(finish)
|
143
|
-
start=finish
|
144
|
-
else
|
145
|
-
duration=minutes(start.hour,start.min,23, 59)
|
146
|
-
start=start+((23-start.hour)*HOUR) +((60-start.min)*MINUTE)
|
147
|
-
end
|
148
|
-
return duration, start
|
149
|
-
end
|
150
|
-
|
151
|
-
# Returns the total number of minutes between two times.
|
152
|
-
#
|
153
|
-
# @param [Integer] start_hour first hour in range
|
154
|
-
# @param [Integer] start_min first minute of first hour in range
|
155
|
-
# @param [Integer] finish_hour last hour in range
|
156
|
-
# @param [Integer] finish_min last minute of last hour in range
|
157
|
-
# @return [Integer] minutes between supplied hours and minutes
|
158
|
-
#
|
159
|
-
# @todo can this method and #diff method be combined?
|
160
|
-
#
|
161
|
-
def minutes(start_hour,start_min,finish_hour,finish_min)
|
162
|
-
|
163
|
-
if (start_hour > finish_hour) || ((finish_hour==start_hour) && (start_min > finish_min))
|
164
|
-
start_hour,start_min,finish_hour,finish_min=finish_hour,finish_min,start_hour,finish_min
|
165
|
-
end
|
166
|
-
|
167
|
-
if (start_hour==finish_hour)
|
168
|
-
retval=self.values[start_hour].wp_minutes(start_min,finish_min)
|
169
|
-
else
|
170
|
-
|
171
|
-
retval=self.values[start_hour].wp_minutes(start_min,59)
|
172
|
-
while (start_hour+1<finish_hour)
|
173
|
-
retval+=self.values[start_hour+1].wp_total
|
174
|
-
start_hour+=1
|
175
|
-
end
|
176
|
-
retval+=self.values[finish_hour].wp_minutes(0,finish_min)
|
177
|
-
end
|
178
|
-
|
179
|
-
return retval
|
180
|
-
end
|
181
|
-
|
182
|
-
|
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
|
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
|
-
|
220
|
-
|
221
|
-
# Returns the first working minute as a <tt>DateTime</tt> or <tt>oo:oo</tt>
|
222
|
-
# when there is no working minutes in the day. Used by the <tt>#subtract</tt> method
|
223
|
-
#
|
224
|
-
# @param [DateTime] time day for which the first working time is sought.
|
225
|
-
# @return [DateTime] the first working time of the day
|
226
|
-
#
|
227
|
-
def first_working_minute(time)
|
228
|
-
if self.first_hour.nil?
|
229
|
-
return time - (HOUR*time.hour) - (MINUTE*time.min)
|
230
|
-
else
|
231
|
-
time = time - HOUR * (time.hour - self.first_hour)
|
232
|
-
time = time - MINUTE * (time.min - self.first_min )
|
233
|
-
return time
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
# Handles the subtraction of a duration from a time in the day.
|
238
|
-
#
|
239
|
-
# @param [DateTime] time when the subtraction starts from
|
240
|
-
# @param [Integer] duration is the number of minutes to subtract from the <tt>time</tt>
|
241
|
-
# @param [Boolean] midnight is a flag used in subtraction to pretend the time is actually midnight
|
242
|
-
# @return [DateTime,Integer,Boolean] Calculated time along with any remaining duration and the midnight flag
|
243
|
-
#
|
244
|
-
def subtract(time,duration,midnight=false)
|
245
|
-
if (time.hour==0 && time.min==0)
|
246
|
-
if midnight
|
247
|
-
duration+=minutes(23,59,23,59)
|
248
|
-
time=time+(HOUR*23)+(MINUTE*59)
|
249
|
-
return calc(time,duration)
|
250
|
-
else
|
251
|
-
return time.prev_day, duration,true
|
252
|
-
end
|
253
|
-
elsif (time.hour==self.first_hour && time.min==self.first_min)
|
254
|
-
time=time-(HOUR*self.first_hour) - (MINUTE*self.first_min)
|
255
|
-
return time.prev_day, duration, true
|
256
|
-
elsif (time.min>0)
|
257
|
-
available_minutes=minutes(0,0,time.hour,time.min-1)
|
258
|
-
else
|
259
|
-
available_minutes=minutes(0,0,time.hour-1,59)
|
260
|
-
end
|
261
|
-
if ((duration+available_minutes)<0) # not enough minutes in the day
|
262
|
-
time = midnight_before(time.prev_day)
|
263
|
-
duration = duration + available_minutes
|
264
|
-
return time, duration, true
|
265
|
-
elsif ((duration+available_minutes)==0)
|
266
|
-
duration=0
|
267
|
-
time=first_working_minute(time)
|
268
|
-
else
|
269
|
-
minutes_this_hour=self.values[time.hour].wp_minutes(0,time.min-1)
|
270
|
-
this_hour=time.hour
|
271
|
-
until (duration==0)
|
272
|
-
if (minutes_this_hour<duration.abs)
|
273
|
-
duration+=minutes_this_hour
|
274
|
-
time = time - (MINUTE*time.min) - HOUR
|
275
|
-
this_hour-=1
|
276
|
-
minutes_this_hour=self.values[this_hour].wp_total
|
277
|
-
else
|
278
|
-
next_hour=(time.min==0)
|
279
|
-
time,duration=self.values[this_hour].wp_calc(time,duration, next_hour)
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
return time,duration, false
|
284
|
-
end
|
285
|
-
|
286
|
-
# Returns the result of adding <tt>duration</tt> to the given <tt>time</tt>
|
287
|
-
# When there are not enough minutes in the day it returns the date
|
288
|
-
# for the start of the following day.
|
289
|
-
#
|
290
|
-
# @param [DateTime] time when the calculation starts from
|
291
|
-
# @param [Integer] duration is the number of minutes to add
|
292
|
-
# @return [DateTime,Integer] Calculated time along with any remaining duration
|
293
|
-
#
|
294
|
-
def add(time,duration)
|
295
|
-
available_minutes=minutes(time.hour,time.min,self.hours-1,59)
|
296
|
-
if ((duration-available_minutes)>0) # not enough minutes left in the day
|
297
|
-
|
298
|
-
result_date= time.next_day - (HOUR*time.hour) - (MINUTE*time.min)
|
299
|
-
duration = duration - available_minutes
|
300
|
-
else
|
301
|
-
total=self.values[time.hour].wp_minutes(time.min,59)
|
302
|
-
if (total==duration) # this hour satisfies
|
303
|
-
result_date=time - (MINUTE*time.min) + (MINUTE*self.values[time.hour].wp_last) + MINUTE
|
304
|
-
duration = 0
|
305
|
-
else
|
306
|
-
result_date = time
|
307
|
-
until (duration==0)
|
308
|
-
if (total<duration)
|
309
|
-
duration-=total
|
310
|
-
result_date=result_date + HOUR - (MINUTE*result_date.min)
|
311
|
-
else
|
312
|
-
result_date,duration=self.values[result_date.hour].wp_calc(result_date,duration)
|
313
|
-
end
|
314
|
-
total=self.values[result_date.hour].wp_total
|
315
|
-
end
|
316
|
-
end
|
317
|
-
end
|
318
|
-
return result_date,duration, false
|
319
|
-
end
|
320
|
-
|
321
|
-
# Returns the start of the next hour.
|
322
|
-
#
|
323
|
-
# The next hour could be the start of the following day.
|
324
|
-
#
|
325
|
-
# @param [DateTime] start is the <tt>DateTime</tt> for which the following hour is required.
|
326
|
-
# @return [DateTime] the start of the next hour following the <tt>DateTime</tt> supplied
|
327
|
-
#
|
328
|
-
def next_hour(start)
|
329
|
-
return start+HOUR-(start.min*MINUTE)
|
330
|
-
end
|
331
|
-
|
332
|
-
# Returns the number of working minutes left in the current hour
|
333
|
-
#
|
334
|
-
# @param [DateTime] start is the <tt>DateTime</tt> for which the remaining working minutes
|
335
|
-
# in the hour are required
|
336
|
-
# @return [Integer] number of remaining working minutes
|
337
|
-
#
|
338
|
-
def minutes_left_in_hour(start)
|
339
|
-
return self.values[start.hour].wp_diff(start.min,60)
|
340
|
-
end
|
341
|
-
|
342
|
-
end
|
343
|
-
end
|