time_keeper 0.1.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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +53 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/time_keeper.rb +7 -0
- data/lib/time_keeper/custom_time.rb +39 -0
- data/lib/time_keeper/parser.rb +7 -0
- data/lib/time_keeper/parser/base.rb +50 -0
- data/lib/time_keeper/parser/meridian.rb +40 -0
- data/lib/time_keeper/parser/military.rb +29 -0
- data/lib/time_keeper/string_minutes_support.rb +19 -0
- data/lib/time_keeper/time_range.rb +39 -0
- data/lib/time_keeper/time_range_collection.rb +29 -0
- data/lib/time_keeper/time_range_manipulation.rb +21 -0
- data/lib/time_keeper/time_span_support.rb +60 -0
- data/spec/lib/time_keeper/custom_time_spec.rb +101 -0
- data/spec/lib/time_keeper/parser/base_spec.rb +99 -0
- data/spec/lib/time_keeper/parser/meridian_spec.rb +76 -0
- data/spec/lib/time_keeper/parser/military_spec.rb +62 -0
- data/spec/lib/time_keeper/time_range_collection_spec.rb +36 -0
- data/spec/lib/time_keeper/time_range_manipulation_spec.rb +102 -0
- data/spec/lib/time_keeper/time_range_spec.rb +96 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/time_keeper_spec.rb +4 -0
- data/time_keeper.gemspec +89 -0
- metadata +231 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module TimeKeeper
|
2
|
+
module TimeRangeManipulation
|
3
|
+
def split_time_range_by_day(range)
|
4
|
+
return [] if range.blank?
|
5
|
+
if range.first.to_date < range.last.to_date
|
6
|
+
out = []
|
7
|
+
current = range.first
|
8
|
+
while current.to_i <= range.last.to_i
|
9
|
+
eod = current.end_of_day
|
10
|
+
eod = range.last if current.to_date == range.last.to_date
|
11
|
+
out << (current .. eod)
|
12
|
+
current = eod + 1.second
|
13
|
+
end
|
14
|
+
out
|
15
|
+
else
|
16
|
+
[range]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
module_function :split_time_range_by_day
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module TimeKeeper::TimeSpanSupport
|
2
|
+
include TimeKeeper::StringMinutesSupport
|
3
|
+
|
4
|
+
def display
|
5
|
+
[
|
6
|
+
[
|
7
|
+
start_time_string,
|
8
|
+
(start_day.to_i > 0) ? "Next Day" : nil,
|
9
|
+
],
|
10
|
+
[
|
11
|
+
end_time_string,
|
12
|
+
(end_day.to_i > 0) ? "Next Day" : nil,
|
13
|
+
]
|
14
|
+
].map { |i| i.compact.join(" ") }.join(" to ")
|
15
|
+
end
|
16
|
+
|
17
|
+
def start_time_string
|
18
|
+
to_s_helper(self.start_time) unless self.start_time.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def start_time_string=(v)
|
22
|
+
begin
|
23
|
+
self.start_time = to_i_helper(v)
|
24
|
+
rescue ArgumentError => e
|
25
|
+
self.errors.add :start_time, e.message
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def end_time_string
|
30
|
+
to_s_helper(self.end_time) unless self.end_time.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def end_time_string=(v)
|
34
|
+
begin
|
35
|
+
self.end_time = to_i_helper(v)
|
36
|
+
rescue ArgumentError => e
|
37
|
+
self.errors.add :end_time, e.message
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def duration_string
|
42
|
+
to_s_helper(duration)
|
43
|
+
end
|
44
|
+
|
45
|
+
def time_range(on)
|
46
|
+
bak, ENV['TZ'] = ENV['TZ'], Time.zone.tzinfo.name
|
47
|
+
on = on.to_time
|
48
|
+
ENV['TZ'] = bak
|
49
|
+
st = on+start_day.days
|
50
|
+
en = on+end_day.days
|
51
|
+
stt = Time.zone.local(st.year, st.month, st.day, start_time/60, start_time % 60).in_time_zone
|
52
|
+
ent = Time.zone.local(en.year, en.month, en.day, end_time/60, end_time % 60).in_time_zone
|
53
|
+
stt..ent
|
54
|
+
end
|
55
|
+
|
56
|
+
def duration
|
57
|
+
((end_day * 24 * 60) + end_time) - ((start_day * 24 * 60) + start_time)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TimeKeeper::CustomTime do
|
4
|
+
subject do
|
5
|
+
TimeKeeper::CustomTime.new("09:45 am")
|
6
|
+
end
|
7
|
+
describe "#initialize" do
|
8
|
+
it "should set the time_in_str variable" do
|
9
|
+
TimeKeeper::CustomTime.new("06:45 am").instance_variable_get('@time_in_str').should eq("06:45 am")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#parse" do
|
14
|
+
it "should set the parsed time object to the appropriate time parser" do
|
15
|
+
subject.parse.instance_variable_get("@parsed_time").class.should eq(TimeKeeper::Parser::Meridian)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should call parse on the time parser object" do
|
19
|
+
time_parser_obj = TimeKeeper::Parser::Meridian.new("06:45 am")
|
20
|
+
TimeKeeper::Parser::Base.stubs(:build).returns(time_parser_obj)
|
21
|
+
time_parser_obj.expects(:parse)
|
22
|
+
subject.parse
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return the custom time object" do
|
26
|
+
subject.parse.should eq(subject)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#in_seconds" do
|
31
|
+
context "when the time is parsed" do
|
32
|
+
before(:each) do
|
33
|
+
subject.instance_variable_set('@parsed_time', TimeKeeper::Parser::Meridian.new("06:45 am").parse)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return the time in seconds" do
|
37
|
+
subject.in_seconds.should eq(24300)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when the time is not parsed" do
|
42
|
+
before(:each) do
|
43
|
+
subject.instance_variable_set('@parsed_time', nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should raise an exception" do
|
47
|
+
lambda{subject.in_seconds}.should raise_exception
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#in_minutes" do
|
53
|
+
context "when the time is parsed" do
|
54
|
+
before(:each) do
|
55
|
+
subject.instance_variable_set('@parsed_time', TimeKeeper::Parser::Meridian.new("06:45 am").parse)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return the time in minutes" do
|
59
|
+
subject.in_minutes.should eq(405)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when the time is not parsed" do
|
64
|
+
before(:each) do
|
65
|
+
subject.instance_variable_set('@parsed_time', nil)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should raise an exception" do
|
69
|
+
lambda{subject.in_minutes}.should raise_exception
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
describe "#in_hours" do
|
74
|
+
context "when the time is parsed" do
|
75
|
+
before(:each) do
|
76
|
+
subject.instance_variable_set('@parsed_time', TimeKeeper::Parser::Meridian.new("06:45 am").parse)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should return the time in hours" do
|
80
|
+
subject.in_hours.should eq(6.75)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when the time is not parsed" do
|
85
|
+
before(:each) do
|
86
|
+
subject.instance_variable_set('@parsed_time', nil)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should raise an exception" do
|
90
|
+
lambda{subject.in_minutes}.should raise_exception
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#to_s" do
|
96
|
+
it "should return formatted hours and minutes" do
|
97
|
+
subject.expects(:in_minutes).twice.returns(405)
|
98
|
+
subject.to_s.should eq("06:45")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TimeKeeper::Parser::Base do
|
4
|
+
|
5
|
+
context "when time_is_valid method is implemented" do
|
6
|
+
before(:each) do
|
7
|
+
TimeKeeper::Parser::Base.any_instance.stubs(:time_is_valid).returns(true)
|
8
|
+
end
|
9
|
+
|
10
|
+
subject do
|
11
|
+
TimeKeeper::Parser::Base.new("11:20 am")
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#initialize" do
|
15
|
+
it "should set the time in string" do
|
16
|
+
TimeKeeper::Parser::Base.new("11:20 am").instance_variable_get('@time_str').should eq("11:20 am")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should raise an exception if the time is not valid" do
|
20
|
+
lambda{TimeKeeper::Parser::Base.new("11:20 xyz")}.should raise_exception
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".build" do
|
25
|
+
context "when the time is in meridian format" do
|
26
|
+
it "should return a meridian time parser object" do
|
27
|
+
TimeKeeper::Parser::Base.build("11:20 am").class.should eq(TimeKeeper::Parser::Meridian)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when the time is in military format" do
|
32
|
+
it "should return a military time parser object" do
|
33
|
+
TimeKeeper::Parser::Base.build("14:20").class.should eq(TimeKeeper::Parser::Military)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#parse" do
|
39
|
+
it "should raise an exception" do
|
40
|
+
lambda{subject.parse}.should raise_exception(NotImplementedError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#extract_hour" do
|
45
|
+
it "should raise an exception" do
|
46
|
+
lambda{subject.send(:extract_hour)}.should raise_exception(NotImplementedError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#extract_min" do
|
51
|
+
it "should assign minute to the @min variable" do
|
52
|
+
subject.send(:extract_min, ":45")
|
53
|
+
subject.instance_variable_get('@min').should eq(45)
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when min is present" do
|
57
|
+
it "should return the number of mins in integer" do
|
58
|
+
subject.send(:extract_min, ":45").should eq(45)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when min is nil or blank" do
|
63
|
+
it "should return 0" do
|
64
|
+
subject.send(:extract_min, "").should eq(0)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when time_is_valid method is not implemented" do
|
71
|
+
before(:each) do
|
72
|
+
TimeKeeper::Parser::Base.any_instance.stubs(:valid?).returns(true)
|
73
|
+
end
|
74
|
+
|
75
|
+
subject do
|
76
|
+
TimeKeeper::Parser::Base.new("06:35")
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#time_is_valid" do
|
80
|
+
it "should raise an exception" do
|
81
|
+
lambda{subject.send(:time_is_valid)}.should raise_exception(NotImplementedError)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe ".meridian_format?" do
|
87
|
+
context "when the time contains am or pm" do
|
88
|
+
it "should return true" do
|
89
|
+
TimeKeeper::Parser::Base.meridian_format?("6:45 Pm").should be_true
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when the time does not contain am or pm" do
|
94
|
+
it "should return false" do
|
95
|
+
TimeKeeper::Parser::Base.meridian_format?("18:45").should be_false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TimeKeeper::Parser::Meridian do
|
4
|
+
subject do
|
5
|
+
TimeKeeper::Parser::Meridian.new("7:45 pm")
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#time_is_valid" do
|
9
|
+
context "when hour and mins are both valid" do
|
10
|
+
it "should return true" do
|
11
|
+
subject.send(:time_is_valid).should be_true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when either hour or min is not valid" do
|
16
|
+
before(:each) do
|
17
|
+
subject.instance_variable_set('@time_str', "07:60 pm")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return false" do
|
21
|
+
subject.send(:time_is_valid).should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should attach an error to the object" do
|
25
|
+
subject.send(:time_is_valid)
|
26
|
+
subject.errors[:base].should_not be_empty
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#extract_hour" do
|
32
|
+
context "when the time contains 12 am" do
|
33
|
+
it "should set hour as 0" do
|
34
|
+
subject.send(:extract_hour, "12", "am")
|
35
|
+
subject.instance_variable_get('@hour').should == 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when the time contains 12 pm" do
|
40
|
+
it "should set hour as 12" do
|
41
|
+
subject.send(:extract_hour, "12", "pm")
|
42
|
+
subject.instance_variable_get('@hour').should == 12
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when the time is between 1 and 11 am" do
|
47
|
+
it "should set hour between 1 to 11" do
|
48
|
+
subject.send(:extract_hour, "9", "am")
|
49
|
+
subject.instance_variable_get('@hour').should == 9
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when the time is between 1 and 12 pm" do
|
54
|
+
it "should set hour between 12 to 23" do
|
55
|
+
subject.send(:extract_hour, "3", "pm")
|
56
|
+
subject.instance_variable_get('@hour').should == 15
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return back the hour object" do
|
61
|
+
subject.send(:extract_hour, "3", "pm").should eq(15)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#parse" do
|
66
|
+
it "should parse the time and set the hours and mins" do
|
67
|
+
subject.parse
|
68
|
+
subject.instance_variable_get('@hour').should eq(19)
|
69
|
+
subject.instance_variable_get('@min').should eq(45)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return back the time parser object" do
|
73
|
+
subject.parse.should eq(subject)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TimeKeeper::Parser::Military do
|
4
|
+
subject do
|
5
|
+
TimeKeeper::Parser::Military.new("19:45")
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#time_is_valid" do
|
9
|
+
context "when hour and mins are both valid" do
|
10
|
+
it "should return true" do
|
11
|
+
subject.send(:time_is_valid).should be_true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when either hour or min is not valid" do
|
16
|
+
before(:each) do
|
17
|
+
subject.instance_variable_set('@time_str', "19:60")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return false" do
|
21
|
+
subject.send(:time_is_valid).should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should attach an error to the object" do
|
25
|
+
subject.send(:time_is_valid)
|
26
|
+
subject.errors[:base].should_not be_empty
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#extract_hour" do
|
32
|
+
context "when hour is present" do
|
33
|
+
it "should set hour" do
|
34
|
+
subject.send(:extract_hour, "15")
|
35
|
+
subject.instance_variable_get("@hour").should eq(15)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when hour is not present" do
|
40
|
+
it "should set hour to zero" do
|
41
|
+
subject.send(:extract_hour, "")
|
42
|
+
subject.instance_variable_get("@hour").should eq(0)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return back the hour object" do
|
47
|
+
subject.send(:extract_hour, "3").should eq(3)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#parse" do
|
52
|
+
it "should parse the time and set the hours and mins" do
|
53
|
+
subject.parse
|
54
|
+
subject.instance_variable_get('@hour').should eq(19)
|
55
|
+
subject.instance_variable_get('@min').should eq(45)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return back the time parser object" do
|
59
|
+
subject.parse.should eq(subject)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TimeKeeper::TimeRangeCollection do
|
4
|
+
subject do
|
5
|
+
TimeKeeper::TimeRangeCollection.new("06:00 pm - 03:00 am\n07:00 - 17:00")
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#initialize" do
|
9
|
+
it "should set the time_ranges_str variable" do
|
10
|
+
TimeKeeper::TimeRangeCollection.new("06:00 pm - 03:00 am\n07:00 - 17:00").instance_variable_get('@time_ranges_str').should eq("06:00 pm-03:00 am\n07:00-17:00")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#parse" do
|
15
|
+
it "should match return proper range sets count" do
|
16
|
+
subject.parse
|
17
|
+
subject.instance_variable_get("@time_ranges").count.should eq(2)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should set the time ranges properly" do
|
21
|
+
subject.parse
|
22
|
+
subject.time_ranges.first.start_time.in_minutes.should eq(1080)
|
23
|
+
subject.time_ranges.first.end_time.in_minutes.should eq(180)
|
24
|
+
subject.time_ranges.first.start_day.should eq(0)
|
25
|
+
subject.time_ranges.first.end_day.should eq(1)
|
26
|
+
subject.time_ranges.last.start_time.in_minutes.should eq(420)
|
27
|
+
subject.time_ranges.last.end_time.in_minutes.should eq(1020)
|
28
|
+
subject.time_ranges.last.start_day.should eq(1)
|
29
|
+
subject.time_ranges.last.end_day.should eq(1)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return the time ranges collection object" do
|
33
|
+
subject.parse.should eq(subject)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|