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  }