github.com/shoshinnikita/budget-manager@v0.7.1-0.20220131195411-8c46ff1c6778/internal/web/pages/statistics/spent_by_day.go (about) 1 package statistics 2 3 import ( 4 "sort" 5 "time" 6 7 "github.com/ShoshinNikita/budget-manager/internal/db" 8 "github.com/ShoshinNikita/budget-manager/internal/pkg/money" 9 ) 10 11 type SpentByDayDataset []SpentByDayData 12 13 type SpentByDayData struct { 14 Year int `json:"year"` 15 Month time.Month `json:"month"` 16 Day int `json:"day"` 17 18 Spent money.Money `json:"spent"` 19 } 20 21 func CalculateSpentByDay(spends []db.Spend, startDate, endDate time.Time) SpentByDayDataset { 22 spentByDay := make(map[time.Time]money.Money) 23 var ( 24 minDate = time.Date(40000, 0, 0, 0, 0, 0, 0, time.UTC) 25 maxDate = time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC) 26 ) 27 for _, spend := range spends { 28 t := time.Date(spend.Year, spend.Month, spend.Day, 0, 0, 0, 0, time.UTC) 29 if t.Before(minDate) { 30 minDate = t 31 } 32 if t.After(maxDate) { 33 maxDate = t 34 } 35 36 spent := spentByDay[t] 37 spent = spent.Add(spend.Cost) 38 spentByDay[t] = spent 39 } 40 41 if !startDate.IsZero() { 42 minDate = time.Date(startDate.Year(), startDate.Month(), startDate.Day(), 0, 0, 0, 0, time.UTC) 43 } 44 if !endDate.IsZero() { 45 maxDate = time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 0, 0, 0, 0, time.UTC) 46 } 47 for t := minDate; t.Before(maxDate) || t.Equal(maxDate); t = t.Add(24 * time.Hour) { 48 if _, ok := spentByDay[t]; !ok { 49 spentByDay[t] = 0 50 } 51 } 52 53 res := make(SpentByDayDataset, 0, len(spentByDay)) 54 for t, spent := range spentByDay { 55 res = append(res, SpentByDayData{ 56 Year: t.Year(), 57 Month: t.Month(), 58 Day: t.Day(), 59 // 60 Spent: spent, 61 }) 62 } 63 64 sort.Slice(res, func(i, j int) bool { 65 if res[i].Year != res[j].Year { 66 return res[i].Year < res[j].Year 67 } 68 if res[i].Month != res[j].Month { 69 return res[i].Month < res[j].Month 70 } 71 return res[i].Day < res[j].Day 72 }) 73 74 return res 75 }