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 }