1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package day
import (
"fmt"
"time"
"ticktock/internal/store"
)
// fmtDur renders a duration like tock's summaries: "1h37m", "50m", "0m".
func fmtDur(d time.Duration) string {
m := int(d.Minutes())
h, m := m/60, m%60
if h > 0 {
return fmt.Sprintf("%dh%dm", h, m)
}
return fmt.Sprintf("%dm", m)
}
// fmtTockDur renders the table's Duration cell like tock list: "51m0s", "1h37m0s".
func fmtTockDur(d time.Duration) string {
s := int(d.Seconds())
h, s := s/3600, s%3600
m, s := s/60, s%60
if h > 0 {
return fmt.Sprintf("%dh%dm%ds", h, m, s)
}
return fmt.Sprintf("%dm%ds", m, s)
}
func fmtRange(e store.Entry) string {
end := " … "
if !e.Running() {
end = e.End.Format("15:04")
}
return e.Start.Format("15:04") + " - " + end
}
// ProjectTotal is one project's summed duration for the day.
type ProjectTotal struct {
Project string
Total time.Duration
}
// Totals sums per-project and grand-total durations, preserving first-seen order.
func Totals(es []store.Entry) ([]ProjectTotal, time.Duration) {
idx := map[string]int{}
var out []ProjectTotal
var grand time.Duration
for _, e := range es {
grand += e.Duration
if i, ok := idx[e.Project]; ok {
out[i].Total += e.Duration
continue
}
idx[e.Project] = len(out)
out = append(out, ProjectTotal{Project: e.Project, Total: e.Duration})
}
return out, grand
}
|