timesheet 0.2.1 → 0.2.2
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/Manifest.txt +1 -0
- data/lib/timesheet.rb +2 -1
- data/lib/timesheet/report_item.rb +53 -0
- data/lib/timesheet/time_entry.rb +14 -0
- data/lib/timesheet/time_report.rb +14 -19
- data/lib/timesheet/timesheet_parser.rb +3 -3
- data/spec/time_entry_spec.rb +18 -2
- data/spec/time_report_spec.rb +3 -2
- metadata +3 -2
data/Manifest.txt
CHANGED
data/lib/timesheet.rb
CHANGED
@@ -9,6 +9,7 @@ require 'yaml'
|
|
9
9
|
require 'yaml/store'
|
10
10
|
require 'timesheet/range_extensions'
|
11
11
|
require 'timesheet/time_entry'
|
12
|
+
require 'timesheet/report_item'
|
12
13
|
require 'timesheet/time_log'
|
13
14
|
require 'timesheet/time_report'
|
14
15
|
require 'timesheet/trollop'
|
@@ -16,7 +17,7 @@ require 'timesheet/timesheet_parser'
|
|
16
17
|
|
17
18
|
class Timesheet
|
18
19
|
|
19
|
-
VERSION = '0.2.
|
20
|
+
VERSION = '0.2.2'
|
20
21
|
|
21
22
|
def self.run(params)
|
22
23
|
command_hash = {}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
class ReportItem < DelegateClass(TimeEntry)
|
4
|
+
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
def initialize( report, time_entry)
|
8
|
+
@time_entry = time_entry
|
9
|
+
super(@time_entry)
|
10
|
+
@report = report
|
11
|
+
end
|
12
|
+
|
13
|
+
def start_time
|
14
|
+
if @time_entry.to_range.include?(@report.report_start)
|
15
|
+
@report.report_start
|
16
|
+
else
|
17
|
+
@time_entry.start_time
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def end_time
|
22
|
+
if to_range.include?(@report.report_end)
|
23
|
+
@report.report_end
|
24
|
+
else
|
25
|
+
@time_entry.end_time
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def formatted_record_number
|
30
|
+
sprintf("%5d", @time_entry.record_number)
|
31
|
+
end
|
32
|
+
|
33
|
+
def formatted_times
|
34
|
+
puts start_time
|
35
|
+
puts end_time
|
36
|
+
str = ""
|
37
|
+
str << start_time.strftime("%m/%d/%Y at %I:%M %p")
|
38
|
+
str << " to "
|
39
|
+
str << end_time.strftime("%m/%d/%Y at ") if ((start_time.year != end_time.year) || (start_time.yday != end_time.yday))
|
40
|
+
str << end_time.strftime("%I:%M %p")
|
41
|
+
end
|
42
|
+
|
43
|
+
def formatted_duration
|
44
|
+
str = ""
|
45
|
+
str << @time_entry.duration.strftime("%d Days ") if @time_entry.duration.days > 0
|
46
|
+
str << @time_entry.duration.strftime("%hh %mm")
|
47
|
+
end
|
48
|
+
|
49
|
+
def <=>(other_time_entry)
|
50
|
+
self.start_time <=> other_time_entry.start_time
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/lib/timesheet/time_entry.rb
CHANGED
@@ -46,5 +46,19 @@ class TimeEntry
|
|
46
46
|
def to_range
|
47
47
|
Range.new(@start_time, @end_time, true)
|
48
48
|
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
label_width = 10
|
52
|
+
str = ""
|
53
|
+
str << "#{"class:".ljust(label_width)}#{self.class}\n"
|
54
|
+
str << "#{"record:".ljust(label_width)}#{record_number}\n"
|
55
|
+
str << "#{"project:".ljust(label_width)}#{project}\n"
|
56
|
+
str << "#{"start:".ljust(label_width)}#{start_time.strftime("%m/%d/%Y at %I:%M %p")}\n"
|
57
|
+
str << "#{"end:".ljust(label_width)}#{end_time.strftime("%m/%d/%Y at %I:%M %p")}\n"
|
58
|
+
str << "#{"duration:".ljust(label_width)}#{duration}\n"
|
59
|
+
str << "#{"comment:".ljust(label_width)}#{comment}\n"
|
60
|
+
|
61
|
+
str
|
62
|
+
end
|
49
63
|
|
50
64
|
end
|
@@ -4,17 +4,16 @@ require 'time'
|
|
4
4
|
class TimeReport
|
5
5
|
|
6
6
|
def initialize(entries)
|
7
|
-
@entries = entries
|
7
|
+
@entries = (entries.nil?) ? [] : entries.map { |entry| ReportItem.new(self, entry)}
|
8
8
|
end
|
9
9
|
|
10
10
|
attr_accessor :entries
|
11
|
+
attr_reader :report_start
|
12
|
+
attr_reader :report_end
|
11
13
|
|
12
|
-
def
|
13
|
-
@
|
14
|
-
|
15
|
-
e.end_time = end_time if e.to_range.include?(end_time)
|
16
|
-
e
|
17
|
-
end
|
14
|
+
def constrain(start_time, end_time)
|
15
|
+
@report_start = start_time
|
16
|
+
@report_end = end_time
|
18
17
|
end
|
19
18
|
|
20
19
|
def report(command_options, outstream = STDOUT)
|
@@ -22,7 +21,7 @@ class TimeReport
|
|
22
21
|
if (@entries.nil? || @entries.empty?)
|
23
22
|
outstream.puts("No data available.")
|
24
23
|
else
|
25
|
-
|
24
|
+
constrain(command_options[:start], command_options[:end])
|
26
25
|
|
27
26
|
detail_report(outstream) if command_options[:detail]
|
28
27
|
summary_report(outstream) if command_options[:summary]
|
@@ -33,29 +32,25 @@ class TimeReport
|
|
33
32
|
private
|
34
33
|
|
35
34
|
def detail_report(outstream)
|
35
|
+
|
36
|
+
# field_names = ["Id", "Project", "Start - Stop", "Hours", "Comment"]
|
37
|
+
# field_methods = [:formatted_record_number, :project, :formatted_times, :formatted_duration, :comment]
|
38
|
+
|
36
39
|
table = Ruport::Data::Table({ :column_names => ["Id", "Project", "Start - Stop", "Hours", "Comment"]}) do |table|
|
37
40
|
@entries.sort.each do |entry|
|
38
41
|
row = []
|
39
42
|
|
40
43
|
# format record number
|
41
|
-
row <<
|
44
|
+
row << entry.formatted_record_number
|
42
45
|
|
43
46
|
# format project
|
44
47
|
row << entry.project
|
45
48
|
|
46
49
|
# format start - stop
|
47
|
-
|
48
|
-
str << entry.start_time.strftime("%m/%d/%Y at %I:%M %p")
|
49
|
-
str << " to "
|
50
|
-
str << entry.end_time.strftime("%m/%d/%Y at ") if ( (entry.start_time.year != entry.end_time.year) && (entry.start_time.yday != entry.end_time.yday))
|
51
|
-
str << entry.end_time.strftime("%I:%M %p")
|
52
|
-
row << str
|
50
|
+
row << entry.formatted_times
|
53
51
|
|
54
52
|
# format duration
|
55
|
-
|
56
|
-
str << entry.duration.strftime("%d Days ") if entry.duration.days > 0
|
57
|
-
str << entry.duration.strftime("%hh %mm")
|
58
|
-
row << str
|
53
|
+
row << entry.formatted_duration
|
59
54
|
|
60
55
|
# format comment
|
61
56
|
row << entry.comment
|
@@ -212,7 +212,7 @@ EOS
|
|
212
212
|
|
213
213
|
when :current_week
|
214
214
|
periods[:start] = Chronic.parse("this week #{WEEK_START} at 12 am")
|
215
|
-
periods[:end] = periods[:start] +
|
215
|
+
periods[:end] = periods[:start] + 1.week
|
216
216
|
|
217
217
|
when :current_month
|
218
218
|
today = Date.today
|
@@ -225,8 +225,8 @@ EOS
|
|
225
225
|
periods[:end] = periods[:start] + 1.day
|
226
226
|
|
227
227
|
when :last_week
|
228
|
-
periods[:start] = Chronic.parse("
|
229
|
-
periods[:end] = periods[:start] +
|
228
|
+
periods[:start] = Chronic.parse("this week #{WEEK_START} at 12 am") - 1.week
|
229
|
+
periods[:end] = periods[:start] + 1.week
|
230
230
|
|
231
231
|
when :last_month
|
232
232
|
today = Date.today
|
data/spec/time_entry_spec.rb
CHANGED
@@ -17,7 +17,8 @@ describe TimeEntry do
|
|
17
17
|
context "Basic Features" do
|
18
18
|
|
19
19
|
before :each do
|
20
|
-
@time_entry = TimeEntry.new("Project", Time.local(2009, 12, 1, 9, 0, 0), Time.local(2009, 12, 1, 17, 0, 0))
|
20
|
+
@time_entry = TimeEntry.new("Project", Time.local(2009, 12, 1, 9, 0, 0), Time.local(2009, 12, 1, 17, 0, 0), "a comment")
|
21
|
+
@time_entry.record_number = 1
|
21
22
|
end
|
22
23
|
|
23
24
|
|
@@ -34,7 +35,8 @@ describe TimeEntry do
|
|
34
35
|
end
|
35
36
|
|
36
37
|
it "should have an initial comment of nil" do
|
37
|
-
|
38
|
+
time_entry = TimeEntry.new("Project", Time.local(2009, 12, 1, 9, 0, 0), Time.local(2009, 12, 1, 17, 0, 0))
|
39
|
+
time_entry.comment.should == nil
|
38
40
|
end
|
39
41
|
|
40
42
|
it "should calculate its duration from start and end times" do
|
@@ -74,6 +76,20 @@ describe TimeEntry do
|
|
74
76
|
it "should not allow assignment to duration" do
|
75
77
|
@time_entry.should_not respond_to :duration=
|
76
78
|
end
|
79
|
+
|
80
|
+
it "should have a to_s method to display its contents" do
|
81
|
+
@time_entry.should respond_to :to_s
|
82
|
+
@time_entry.to_s.should eql( <<EOS
|
83
|
+
class: TimeEntry
|
84
|
+
record: 1
|
85
|
+
project: Project
|
86
|
+
start: 12/01/2009 at 09:00 AM
|
87
|
+
end: 12/01/2009 at 05:00 PM
|
88
|
+
duration: 0 seconds 0 minutes 8 hours 0 days
|
89
|
+
comment: a comment
|
90
|
+
EOS
|
91
|
+
)
|
92
|
+
end
|
77
93
|
|
78
94
|
end
|
79
95
|
|
data/spec/time_report_spec.rb
CHANGED
@@ -13,13 +13,13 @@ describe TimeReport do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should be able to trim its entries to a specific time span" do
|
16
|
-
@time_report.
|
16
|
+
@time_report.constrain(Time.local(2009, 12, 1, 11, 0, 0), Time.local(2009, 12, 5, 12, 0, 0))
|
17
17
|
@time_report.entries[0].start_time.should eql(Time.local(2009, 12, 1, 11, 0, 0))
|
18
18
|
@time_report.entries[-1].end_time.should eql(Time.local(2009, 12, 5, 12, 0, 0))
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should leave entries alone when the trim span is outside the entry range" do
|
22
|
-
@time_report.
|
22
|
+
@time_report.constrain(Time.local(2009, 11, 1, 0, 0, 0), Time.local(2009, 12, 31, 0, 0, 0))
|
23
23
|
@time_report.entries[0].start_time.should eql(Time.local(2009, 12, 1, 9, 0, 0))
|
24
24
|
@time_report.entries[-1].end_time.should eql(Time.local(2009, 12, 5, 17, 0, 0))
|
25
25
|
end
|
@@ -92,6 +92,7 @@ EOS
|
|
92
92
|
|
93
93
|
it "should be able to produce a byday report" do
|
94
94
|
@entries << TimeEntry.new("ProjectB", Time.local(2009, 12, 1, 17, 0, 0), Time.local(2009, 12, 1, 19, 0, 0), "another comment")
|
95
|
+
@time_report = TimeReport.new(@entries)
|
95
96
|
|
96
97
|
command_options = {:byday => true, :start => Time.local(2009, 12, 1), :end => Time.local(2009, 12, 6)}
|
97
98
|
stream = StringIO.new
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timesheet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John F. Schank III
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-02-07 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -225,6 +225,7 @@ files:
|
|
225
225
|
- lib/timesheet.rb
|
226
226
|
- lib/timesheet/range_extensions.rb
|
227
227
|
- lib/timesheet/time_entry.rb
|
228
|
+
- lib/timesheet/report_item.rb
|
228
229
|
- lib/timesheet/time_log.rb
|
229
230
|
- lib/timesheet/time_report.rb
|
230
231
|
- lib/timesheet/timesheet_parser.rb
|