diff options
Diffstat (limited to 'cmd/gen-imworkingon/calendar.go')
-rw-r--r-- | cmd/gen-imworkingon/calendar.go | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/cmd/gen-imworkingon/calendar.go b/cmd/gen-imworkingon/calendar.go new file mode 100644 index 0000000..29c3318 --- /dev/null +++ b/cmd/gen-imworkingon/calendar.go @@ -0,0 +1,122 @@ +package main + +import ( + "time" +) + +////////////////////////////////////////////////////////////////////// + +type Date struct { + Year int + Month time.Month + Day int +} + +func DateOf(t time.Time) Date { + y, m, d := t.Date() + return Date{Year: y, Month: m, Day: d} +} + +func (d Date) Time() time.Time { + return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, time.Local) +} + +func (d Date) AddDays(delta int) Date { + return DateOf(d.Time().AddDate(0, 0, delta)) +} + +func (d Date) Weekday() time.Weekday { + return d.Time().Weekday() +} + +func (a Date) Cmp(b Date) int { + switch { + case a.Year < b.Year: + return -1 + case a.Year > b.Year: + return 1 + } + switch { + case a.Month < b.Month: + return -1 + case a.Month > b.Month: + return 1 + } + switch { + case a.Day < b.Day: + return -1 + case a.Day > b.Day: + return 1 + } + return 0 +} + +////////////////////////////////////////////////////////////////////// + +type CalendarDay[T any] struct { + Date + Data T +} + +////////////////////////////////////////////////////////////////////// + +// keyed by time.Weekday +type CalendarWeek[T any] [7]CalendarDay[T] + +////////////////////////////////////////////////////////////////////// + +// must be sorted, must be non-sparse +type Calendar[T any] []CalendarWeek[T] + +func (c Calendar[T]) NumWeekdaysInMonth(weekday time.Weekday, target Date) int { + num := 0 + for _, w := range c { + if w[weekday].Date == (Date{}) { + continue + } + switch { + case w[weekday].Year == target.Year: + switch { + case w[weekday].Month == target.Month: + num++ + case w[weekday].Month > target.Month: + return num + } + case w[weekday].Year > target.Year: + return num + } + } + return num +} + +////////////////////////////////////////////////////////////////////// + +func BuildCalendar[T any](things []T, dateOfThing func(T) Date) Calendar[T] { + if len(things) == 0 { + return nil + } + + newestDate := DateOf(time.Now().Local()) + + oldestDate := dateOfThing(things[0]) + byDate := make(map[Date]T, len(things)) + for _, thing := range things { + date := dateOfThing(thing) + if oldestDate.Cmp(date) > 0 { + oldestDate = date + } + byDate[date] = thing + } + + var ret Calendar[T] + for date := oldestDate; date.Cmp(newestDate) <= 0; date = date.AddDays(1) { + if len(ret) == 0 || date.Weekday() == 0 { + ret = append(ret, CalendarWeek[T]{}) + } + ret[len(ret)-1][date.Weekday()] = CalendarDay[T]{ + Date: date, + Data: byDate[date], + } + } + return ret +} |