Skip to content

Commit 1ebbb4b

Browse files
author
KonstantinGasser
committed
Merge branch 'main' into report_issue#88
2 parents d65df3c + b472a66 commit 1ebbb4b

File tree

5 files changed

+67
-7
lines changed

5 files changed

+67
-7
lines changed

cli/list.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cli
22

33
import (
44
"strconv"
5+
"time"
56

67
"github.com/dominikbraun/timetrace/core"
78
"github.com/dominikbraun/timetrace/out"
@@ -115,7 +116,11 @@ func listRecordsCommand(t *core.Timetrace) *cobra.Command {
115116
rows[i][5] = billable
116117
}
117118

118-
out.Table([]string{"#", "Key", "Project", "Start", "End", "Billable"}, rows, nil)
119+
footer := make([]string, 6)
120+
footer[len(footer)-2] = "Total: "
121+
footer[len(footer)-1] = t.Formatter().FormatDuration(getTotalTrackedTime(records))
122+
123+
out.Table([]string{"#", "Key", "Project", "Start", "End", "Billable"}, rows, footer)
119124
},
120125
}
121126

@@ -158,3 +163,18 @@ func removeModules(allProjects []*core.Project) []*core.Project {
158163

159164
return parentProjects
160165
}
166+
167+
func getTotalTrackedTime(records []*core.Record) time.Duration {
168+
var totalTime time.Duration
169+
for _, record := range records {
170+
if record.End != nil {
171+
totalTime += record.End.Sub(record.Start)
172+
} else {
173+
// If the current record has no end time, then add the total time
174+
// elapsed from the start of the record.
175+
// TODO: test this scenario
176+
totalTime += time.Since(record.Start)
177+
}
178+
}
179+
return totalTime
180+
}

cli/list_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cli
33
import (
44
"reflect"
55
"testing"
6+
"time"
67

78
"github.com/dominikbraun/timetrace/core"
89
)
@@ -114,3 +115,38 @@ func TestFilterProjectRecords(t *testing.T) {
114115
}
115116
}
116117
}
118+
119+
func TestTotalTrackedTime(t *testing.T) {
120+
tt := []struct {
121+
records []*core.Record
122+
expected time.Duration
123+
}{
124+
{records: []*core.Record{
125+
{
126+
Start: time.Date(2021, 06, 07, 16, 00, 00, 00, time.Local), // 4:00PM
127+
End: timePtr(time.Date(2021, 06, 07, 16, 25, 00, 00, time.Local)), // 4:25PM
128+
},
129+
{
130+
Start: time.Date(2021, 06, 07, 16, 30, 00, 00, time.Local), // 4:30PM
131+
End: timePtr(time.Date(2021, 06, 07, 16, 50, 00, 00, time.Local)), // 4:50PM
132+
},
133+
{
134+
Start: time.Date(2021, 06, 07, 16, 55, 00, 00, time.Local), // 4:55PM
135+
End: timePtr(time.Date(2021, 06, 07, 17, 10, 00, 00, time.Local)), // 5:10PM
136+
},
137+
},
138+
expected: time.Duration(time.Hour),
139+
},
140+
}
141+
for _, test := range tt {
142+
totalTime := getTotalTrackedTime(test.records)
143+
if totalTime != test.expected {
144+
t.Fatalf("error when %v != %v", totalTime, test.expected)
145+
}
146+
}
147+
}
148+
149+
// timePtr gives a pointer of `time.Time` (an alias of int64).
150+
func timePtr(t time.Time) *time.Time {
151+
return &t
152+
}

core/formatter.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,25 +83,25 @@ func (f *Formatter) RecordKey(record *Record) string {
8383
// FormatTodayTime returns the formated string of the total
8484
// time of today follwoing the format convention
8585
func (f *Formatter) FormatTodayTime(report *Report) string {
86-
return f.formatDuration(report.TrackedTimeToday)
86+
return f.FormatDuration(report.TrackedTimeToday)
8787
}
8888

8989
// FormatCurrentTime returns the formated string of the current
9090
// report time follwoing the format convention
9191
func (f *Formatter) FormatCurrentTime(report *Report) string {
92-
return f.formatDuration(*report.TrackedTimeCurrent)
92+
return f.FormatDuration(*report.TrackedTimeCurrent)
9393
}
9494

9595
// FormatBreakTime returns the formated string of the total time
9696
// taking breaks today following the format convention
9797
func (f *Formatter) FormatBreakTime(report *Report) string {
98-
return f.formatDuration(report.BreakTimeToday)
98+
return f.FormatDuration(report.BreakTimeToday)
9999
}
100100

101-
// formatDuration formats the passed duration into a string.
101+
// FormatDuration formats the passed duration into a string.
102102
// The format will be "8h 24min". If the duration is less then 60 secods
103103
// the format will be "0h 0min 12sec".
104-
func (f *Formatter) formatDuration(duration time.Duration) string {
104+
func (f *Formatter) FormatDuration(duration time.Duration) string {
105105

106106
hours := int64(duration.Hours()) % 60
107107
minutes := int64(duration.Minutes()) % 60

core/timetrace_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func TestFormatDuration(t *testing.T) {
4040
formatter := Formatter{}
4141

4242
for _, test := range tt {
43-
strFormat := formatter.formatDuration(test.Duration)
43+
strFormat := formatter.FormatDuration(test.Duration)
4444
if strFormat != test.Expected {
4545
t.Fatalf("format error: %s != %s", strFormat, test.Expected)
4646
}

out/out.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ func setHeaderColor(table *tablewriter.Table, header []string) {
7777
func headersWithPadding(headers []string) []string {
7878
newHeaders := make([]string, len(headers))
7979
for idx, val := range headers {
80+
// Do not pad empty headers.
81+
if val == "" {
82+
continue
83+
}
8084
newHeaders[idx] = " " + val + " "
8185
}
8286
return newHeaders

0 commit comments

Comments
 (0)