81 lines
2 KiB
Go
81 lines
2 KiB
Go
package lib
|
|
|
|
import (
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
// TotalTime represents the time spent per project and activity including a total summary.
|
|
type TotalTime struct {
|
|
Totals []*TotalTimeEntry
|
|
TotalSum time.Duration
|
|
}
|
|
|
|
// TotalTimeEntry represents the time spent for a project and an activity.
|
|
type TotalTimeEntry struct {
|
|
ProjectID string
|
|
Project string
|
|
ActivityID string
|
|
Activity string
|
|
Duration time.Duration
|
|
}
|
|
|
|
// GetTimeTotals collects the time spent per project and activity for a time range.
|
|
func GetTimeTotals(start, end time.Time) (TotalTime, error) {
|
|
totalTime := TotalTime{
|
|
Totals: []*TotalTimeEntry{},
|
|
}
|
|
|
|
entries, entriesErr := readTimeRange(start, end)
|
|
if entriesErr != nil {
|
|
return totalTime, entriesErr
|
|
}
|
|
if len(entries) == 0 {
|
|
return totalTime, nil
|
|
}
|
|
|
|
totalsMap := make(map[string]map[string]time.Duration)
|
|
for _, entry := range entries {
|
|
project, projectFound := totalsMap[entry.ProjectID]
|
|
if !projectFound {
|
|
project = make(map[string]time.Duration)
|
|
totalsMap[entry.ProjectID] = project
|
|
}
|
|
|
|
activity := project[entry.ActivityID]
|
|
project[entry.ActivityID] = activity + entry.End.Sub(entry.Start)
|
|
}
|
|
if len(totalsMap) == 0 {
|
|
return totalTime, nil
|
|
}
|
|
|
|
for projectID, activities := range totalsMap {
|
|
for activity, duration := range activities {
|
|
totalEntry := TotalTimeEntry{
|
|
ProjectID: projectID,
|
|
ActivityID: activity,
|
|
Duration: duration,
|
|
}
|
|
totalTime.Totals = append(totalTime.Totals, &totalEntry)
|
|
totalTime.TotalSum = totalTime.TotalSum + duration
|
|
}
|
|
}
|
|
|
|
return totalTime, nil
|
|
}
|
|
|
|
// GetTimeSummary gathers time entries for a given day. The entries are sorted by start time ascending.
|
|
func GetTimeSummary() ([]*Time, error) {
|
|
dayStart := time.Now().Truncate(24 * time.Hour)
|
|
dayEnd := time.Now().Truncate(24*time.Hour).AddDate(0, 0, 1).Add(-1 * time.Second)
|
|
entries, entriesErr := readTimeRange(dayStart, dayEnd)
|
|
if entriesErr != nil {
|
|
return nil, entriesErr
|
|
}
|
|
|
|
sort.Slice(entries, func(i, j int) bool {
|
|
return entries[i].Start.Before(entries[j].Start)
|
|
})
|
|
|
|
return entries, nil
|
|
}
|