package model import ( "fmt" "strconv" "strings" "time" ) type Birthday struct { Name string Email string Phone string YearOfBirth int MonthOfBirth int DayOfBirth int } func (b *Birthday) Filename() string { return fmt.Sprintf("%d_%d_%d_%s.png", b.YearOfBirth, b.MonthOfBirth, b.DayOfBirth, b.Phone) } func (b *Birthday) Time() time.Time { return time.Date(b.YearOfBirth, time.Month(b.MonthOfBirth), b.DayOfBirth, 0, 0, 0, 0, time.Now().Location()) } func NewBirthdayFromRecord(record []string) (*Birthday, error) { if len(record) != 4 { return nil, fmt.Errorf("invalid length %d for record", len(record)) } dateComponents := strings.Split(strings.TrimSpace(record[3]), "/") if len(dateComponents) != 3 { return nil, fmt.Errorf("invalid date format in %q", strings.TrimSpace(record[3])) } dayOfBirth, err := strconv.Atoi(dateComponents[0]) if err != nil { return nil, fmt.Errorf("error parsing day of birth from %q: %w", dateComponents[0], err) } monthOfBirth, err := strconv.Atoi(dateComponents[1]) if err != nil { return nil, fmt.Errorf("error parsing month of birth from %q: %w", dateComponents[1], err) } yearOfBirth, err := strconv.Atoi(dateComponents[2]) if err != nil { return nil, fmt.Errorf("error parsing year of birth from %q: %w", dateComponents[2], err) } b := &Birthday{ Name: strings.TrimSpace(record[0]), Email: strings.TrimSpace(record[1]), Phone: strings.TrimSpace(record[2]), YearOfBirth: yearOfBirth, MonthOfBirth: monthOfBirth, DayOfBirth: dayOfBirth, } return b, nil } func FilterByYear(birthdays []*Birthday, year int) []*Birthday { filteredBirthdays := []*Birthday{} for _, birthday := range birthdays { if birthday.YearOfBirth == year { filteredBirthdays = append(filteredBirthdays, birthday) } } return filteredBirthdays } func FilterByMonth(birthdays []*Birthday, month int) []*Birthday { filteredBirthdays := []*Birthday{} for _, birthday := range birthdays { if birthday.MonthOfBirth == month { filteredBirthdays = append(filteredBirthdays, birthday) } } return filteredBirthdays } func FilterByDay(birthdays []*Birthday, day int) []*Birthday { filteredBirthdays := []*Birthday{} for _, birthday := range birthdays { if birthday.DayOfBirth == day { filteredBirthdays = append(filteredBirthdays, birthday) } } return filteredBirthdays } func FilterByDate(birthdays []*Birthday, day, month, year int) []*Birthday { filteredBirthdays := []*Birthday{} for _, birthday := range birthdays { if birthday.DayOfBirth == day && birthday.MonthOfBirth == month && birthday.YearOfBirth == year { filteredBirthdays = append(filteredBirthdays, birthday) } } return filteredBirthdays } func NextBirthdayDate(birthdays []*Birthday, now time.Time) (int, int, int) { nowRounded := now.Round(24 * time.Hour) var nextBirthday *Birthday for _, birthday := range birthdays { if nextBirthday == nil { nextBirthday = birthday continue } birthdayTime := birthday.Time() nextBirthdayTime := nextBirthday.Time() if nextBirthdayTime.Before(nowRounded) && birthdayTime.After(nowRounded) { nextBirthday = birthday continue } if birthdayTime.Before(nextBirthdayTime) { if birthdayTime.After(nowRounded) || nextBirthdayTime.Before(nowRounded) { nextBirthday = birthday } } } return nextBirthday.DayOfBirth, nextBirthday.MonthOfBirth, nextBirthday.YearOfBirth } func NextBirthdays(birthdays []*Birthday, now time.Time) []*Birthday { day, month, year := NextBirthdayDate(birthdays, now) return FilterByDate(birthdays, day, month, year) }