Skip to content

Commit

Permalink
Merge pull request #106 from obnoxiousnerd/feature_total_tracked_time
Browse files Browse the repository at this point in the history
  • Loading branch information
dominikbraun authored Jun 7, 2021
2 parents a1544ae + 3603ab2 commit b472a66
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 7 deletions.
22 changes: 21 additions & 1 deletion cli/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"strconv"
"time"

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

out.Table([]string{"#", "Key", "Project", "Start", "End", "Billable"}, rows, nil)
footer := make([]string, 6)
footer[len(footer)-2] = "Total: "
footer[len(footer)-1] = t.Formatter().FormatDuration(getTotalTrackedTime(records))

out.Table([]string{"#", "Key", "Project", "Start", "End", "Billable"}, rows, footer)
},
}

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

return parentProjects
}

func getTotalTrackedTime(records []*core.Record) time.Duration {
var totalTime time.Duration
for _, record := range records {
if record.End != nil {
totalTime += record.End.Sub(record.Start)
} else {
// If the current record has no end time, then add the total time
// elapsed from the start of the record.
// TODO: test this scenario
totalTime += time.Since(record.Start)
}
}
return totalTime
}
36 changes: 36 additions & 0 deletions cli/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cli
import (
"reflect"
"testing"
"time"

"github.com/dominikbraun/timetrace/core"
)
Expand Down Expand Up @@ -114,3 +115,38 @@ func TestFilterProjectRecords(t *testing.T) {
}
}
}

func TestTotalTrackedTime(t *testing.T) {
tt := []struct {
records []*core.Record
expected time.Duration
}{
{records: []*core.Record{
{
Start: time.Date(2021, 06, 07, 16, 00, 00, 00, time.Local), // 4:00PM
End: timePtr(time.Date(2021, 06, 07, 16, 25, 00, 00, time.Local)), // 4:25PM
},
{
Start: time.Date(2021, 06, 07, 16, 30, 00, 00, time.Local), // 4:30PM
End: timePtr(time.Date(2021, 06, 07, 16, 50, 00, 00, time.Local)), // 4:50PM
},
{
Start: time.Date(2021, 06, 07, 16, 55, 00, 00, time.Local), // 4:55PM
End: timePtr(time.Date(2021, 06, 07, 17, 10, 00, 00, time.Local)), // 5:10PM
},
},
expected: time.Duration(time.Hour),
},
}
for _, test := range tt {
totalTime := getTotalTrackedTime(test.records)
if totalTime != test.expected {
t.Fatalf("error when %v != %v", totalTime, test.expected)
}
}
}

// timePtr gives a pointer of `time.Time` (an alias of int64).
func timePtr(t time.Time) *time.Time {
return &t
}
10 changes: 5 additions & 5 deletions core/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,25 @@ func (f *Formatter) RecordKey(record *Record) string {
// FormatTodayTime returns the formated string of the total
// time of today follwoing the format convention
func (f *Formatter) FormatTodayTime(report *Report) string {
return f.formatDuration(report.TrackedTimeToday)
return f.FormatDuration(report.TrackedTimeToday)
}

// FormatCurrentTime returns the formated string of the current
// report time follwoing the format convention
func (f *Formatter) FormatCurrentTime(report *Report) string {
return f.formatDuration(*report.TrackedTimeCurrent)
return f.FormatDuration(*report.TrackedTimeCurrent)
}

// FormatBreakTime returns the formated string of the total time
// taking breaks today following the format convention
func (f *Formatter) FormatBreakTime(report *Report) string {
return f.formatDuration(report.BreakTimeToday)
return f.FormatDuration(report.BreakTimeToday)
}

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

hours := int64(duration.Hours()) % 60
minutes := int64(duration.Minutes()) % 60
Expand Down
2 changes: 1 addition & 1 deletion core/timetrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestFormatDuration(t *testing.T) {
formatter := Formatter{}

for _, test := range tt {
strFormat := formatter.formatDuration(test.Duration)
strFormat := formatter.FormatDuration(test.Duration)
if strFormat != test.Expected {
t.Fatalf("format error: %s != %s", strFormat, test.Expected)
}
Expand Down
4 changes: 4 additions & 0 deletions out/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ func setHeaderColor(table *tablewriter.Table, header []string) {
func headersWithPadding(headers []string) []string {
newHeaders := make([]string, len(headers))
for idx, val := range headers {
// Do not pad empty headers.
if val == "" {
continue
}
newHeaders[idx] = " " + val + " "
}
return newHeaders
Expand Down

0 comments on commit b472a66

Please sign in to comment.