package main_test import ( "fmt" "iter" "strings" "testing" "time" "github.com/matryer/is" cal "go.sour.is/cal" ) func TestDay(t *testing.T) { tests := []struct { name string dayOfWeek cal.Day weekOfMonth int string string }{ { "test monday 0", cal.Monday, 0, "Mon", }, { "test monday 1", cal.Monday, 1, "1Mon", }, { "test monday 5", cal.Monday, 5, "5Mon", }, { "test monday -1", cal.Monday, -1, "-1Mon", }, { "test monday -5", cal.Monday, -5, "-5Mon", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { is := is.New(t) day := cal.NewDay(tt.dayOfWeek, tt.weekOfMonth) is.Equal(day.Day(), tt.dayOfWeek) is.Equal(day.WeekOfMonth(), tt.weekOfMonth) is.Equal(day.String(), tt.string) }) } } func TestMonth(t *testing.T) { tests := []struct { month cal.Month dayOfMonth int string string }{ { cal.January, 0, "Jan", }, { cal.February, 1, "Feb1", }, { cal.March, 31, "Mar31", }, {month: cal.April, string: "Apr"}, {month: cal.May, string: "May"}, {month: cal.June, string: "Jun"}, {month: cal.July, string: "Jul"}, {month: cal.August, string: "Aug"}, {month: cal.September, string: "Sep"}, {month: cal.October, string: "Oct"}, {month: cal.November, string: "Nov"}, {month: cal.December, string: "Dec"}, } for i, tt := range tests { t.Run(fmt.Sprintf("%d %s %d %s", i, tt.month, tt.dayOfMonth, tt.string), func(t *testing.T) { is := is.New(t) month := cal.NewMonth(tt.month, tt.dayOfMonth) is.Equal(month.Month(), tt.month) is.Equal(month.DayOfMonth(), tt.dayOfMonth) is.Equal(month.String(), tt.string) }) } } func TestWeek(t *testing.T) { tests := []struct { name string week int string string }{ { "test week 1", 1, "w01", }, { "test week 52", 52, "w52", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { is := is.New(t) week := cal.NewWeek(tt.week) is.Equal(week.WeekOfYear(), tt.week) is.Equal(week.String(), tt.string) }) } } func TestDate(t *testing.T) { tests := []struct { date cal.Date string string }{ { cal.Date{ Year: 2022, }, "2022", }, { cal.Date{ Year: 2022, Month: 2, }, "2022-02", }, { cal.Date{ Year: 2022, Month: 1, Day: 1, }, "2022-01-01", }, { cal.Date{ Year: 2022, WeekOfYear: []cal.Week{ cal.NewWeek(1), }, }, "2022 w01", }, { cal.Date{ Year: 2022, WeekOfYear: []cal.Week{ cal.NewWeek(1), cal.NewWeek(4), }, }, "2022 w01, w04", }, { cal.Date{ Year: 2022, MonthOfYear: []cal.Month{ cal.NewMonth(cal.January, 17), }, }, "2022 Jan17", }, { cal.Date{ Year: 2022, MonthOfYear: []cal.Month{ cal.NewMonth(cal.January, 1), cal.NewMonth(cal.December, -1), }, }, "2022 Jan1, Dec-1", }, { cal.Date{ Year: 2022, MonthOfYear: []cal.Month{ cal.January, }, DayOfWeek: []cal.Day{ cal.NewDay(cal.Monday, 2), }, }, "2022 Jan 2Mon", }, { cal.Date{ Year: 2022, WeekOfYear: []cal.Week{ cal.NewWeek(6), }, DayOfWeek: []cal.Day{ cal.Tuesday, }, }, "2022 w06 Tue", }, { cal.Date{ Year: 2022, Month: 8, DayOfWeek: []cal.Day{ cal.Wednesday, }, }, "2022-08 Wed", }, { cal.Date{ Year: 2022, Month: 8, DayOfWeek: []cal.Day{ cal.Thursday, cal.Friday, cal.Saturday, cal.Sunday, }, }, "2022-08 Thu, Fri, Sat, Sun", }, { cal.Date{}, "", }, } for i, tt := range tests { t.Run(fmt.Sprintf("%d %s", i, tt.string), func(t *testing.T) { _ = i is := is.New(t) s := tt.date.String() is.Equal(s, tt.string) }) } } func TestMonthParse(t *testing.T) { tests := []struct { month cal.Month day int string string }{ { cal.January, 1, "Jan1", }, { cal.March, 2, "March2", }, { cal.February, 3, "feb3", }, { cal.April, -3, "april-3", }, { cal.May, 0, "MAY", }, { cal.June, -30, "JUN-30", }, { cal.July, 4, "jul4", }, { cal.August, 3, "aug3", }, { cal.September, 21, "sept21", }, { cal.October, 31, "Oct31", }, { cal.November, 15, "nov15", }, { cal.December, 25, "december25", }, } for _, tt := range tests { t.Run(tt.string, func(t *testing.T) { is := is.New(t) var m cal.Month i, err := m.Parse(tt.string) is.NoErr(err) is.Equal(m.Month(), tt.month) is.Equal(m.DayOfMonth(), tt.day) is.Equal(i, len(tt.string)) }) } } func TestDayParse(t *testing.T) { tests := []struct { day cal.Day week int string string }{ { cal.Monday, 1, "1monday", }, { cal.Tuesday, 2, "2Tuesday", }, { cal.Wednesday, 3, "3Wed", }, { cal.Thursday, 4, "4Thur", }, { cal.Friday, -5, "-5Friday", }, { cal.Saturday, -2, "-2Saturday", }, { cal.Sunday, -1, "-1Sunday", }, } for _, tt := range tests { t.Run(tt.string, func(t *testing.T) { is := is.New(t) var d cal.Day i, err := d.Parse(tt.string) is.NoErr(err) is.Equal(d.Day(), tt.day) is.Equal(d.WeekOfMonth(), tt.week) is.Equal(i, len(tt.string)) }) } } func TestWeekParse(t *testing.T) { tests := []struct { week int string string }{ { 1, "w01", }, { 52, "w52", }, } for _, tt := range tests { t.Run(tt.string, func(t *testing.T) { is := is.New(t) var w cal.Week i, err := w.Parse(tt.string) is.NoErr(err) is.Equal(w.WeekOfYear(), tt.week) is.Equal(i, len(tt.string)) }) } } func TestDateParse(t *testing.T) { tests := []struct { date cal.Date string string extra string }{ { date: cal.Date{Year: 2024}, string: "2024", }, { date: cal.Date{Year: 2024}, string: "2024 ", extra: "make food", }, { date: cal.Date{Year: 2024, WeekOfYear: []cal.Week{cal.NewWeek(5)}}, string: "2024 w05", }, { date: cal.Date{Year: 2024, DayOfWeek: []cal.Day{cal.NewDay(cal.Monday, 2)}}, string: "2024 2mon", }, { date: cal.Date{Year: 2024, WeekOfYear: []cal.Week{cal.NewWeek(5), cal.NewWeek(10)}}, string: "2024 w05, w10", }, { date: cal.Date{Year: 2024, WeekOfYear: []cal.Week{cal.NewWeek(5)}, DayOfWeek: []cal.Day{cal.NewDay(cal.Monday, 0)}}, string: "2024 w05 mon", }, { date: cal.Date{Year: 2024, WeekOfYear: []cal.Week{cal.NewWeek(5)}}, string: "2024 w05 ", extra: "monitoring", }, { date: cal.Date{ Year: 2024, WeekOfYear: []cal.Week{cal.NewWeek(5), cal.NewWeek(17)}, DayOfWeek: []cal.Day{cal.NewDay(cal.Monday, 0), cal.NewDay(cal.Friday, 0)}, }, string: "2024 w05 mon, w17 fri", }, { date: cal.Date{ Year: 2024, MonthOfYear: []cal.Month{cal.NewMonth(cal.September, 0)}, DayOfWeek: []cal.Day{cal.NewDay(cal.Monday, 1)}, }, string: "2024 Sept 1mon", }, { date: cal.Date{ Year: 2024, MonthOfYear: []cal.Month{cal.NewMonth(cal.September, 1)}, }, string: "2024 Sept1 ", extra: "monitoring", }, { date: cal.Date{ Year: 2024, MonthOfYear: []cal.Month{ cal.NewMonth(cal.September, 1), cal.NewMonth(cal.October, -1), }, }, string: "2024 Sept1, October-1 ", extra: "monitoring", }, { date: cal.Date{ Year: 2024, MonthOfYear: []cal.Month{cal.NewMonth(cal.September, 1)}, }, string: "2024 Sept1 ", extra: "monitoring", }, { date: cal.Date{ Year: 2024, MonthOfYear: []cal.Month{cal.NewMonth(cal.August, 0), cal.NewMonth(cal.October, 0)}, DayOfWeek: []cal.Day{cal.NewDay(cal.Monday, 2), cal.NewDay(cal.Friday, -1)}, }, string: "2024 Aug 2mon, Oct -1fri", }, { date: cal.Date{Year: 2024, Month: 5}, string: "2024-05", }, { date: cal.Date{Year: 2024, Month: 5, DayOfWeek: []cal.Day{cal.NewDay(cal.Monday, 2)}}, string: "2024-05 2mon", }, { date: cal.Date{Year: 2024, Month: 5, DayOfWeek: []cal.Day{ cal.NewDay(cal.Monday, 2), cal.NewDay(cal.Thursday, 3), }}, string: "2024-05 2mon, 3thur", }, { date: cal.Date{Year: 2024, Month: 5, DayOfWeek: []cal.Day{ cal.NewDay(cal.Monday, 2), cal.NewDay(cal.Thursday, 3), }}, string: "2024-05 2mon, 3thur ", extra: "make food", }, { date: cal.Date{Year: 2024, Month: 5, Day: 14}, string: "2024-05-14", }, { date: cal.Date{Year: 2024, Month: 5, Day: 14}, string: "2024-05-14 ", extra: "make food", }, } for i, tt := range tests { t.Run(fmt.Sprintf("%d %s%s", i, tt.string, tt.extra), func(t *testing.T) { is := is.New(t) var d cal.Date i, err := d.Parse(tt.string + tt.extra) is.NoErr(err) is.Equal(fmt.Sprintf("%#v", d), fmt.Sprintf("%#v", tt.date)) is.Equal(d, tt.date) is.Equal(i, len(tt.string)) }) } } func TestDateProject(t *testing.T) { type test struct { date string start string out string } tests := []test{ {"2024-05-14", "2024-05-14", "2024-05-14"}, {"2024-05-14", "2024-06-24", "2024-06-24"}, {"2024-05", "2024-05-01", "2024-05-31"}, {"2024-05", "2025-02-01", "2025-02-28"}, {"2024-05 2mon", "2025-02-01", "2025-02-10"}, {"2024-05 2mon, 2fri", "2025-02-11", "2025-02-14"}, {"2024-05 -1mon, -2fri", "2025-02-01", "2025-02-24 2025-02-21"}, {"2024 feb -1mon, feb -2fri", "2025-02-01", "2025-02-24 2025-02-21"}, {"2024", "2025-02-01", "2025-12-31"}, {"2024 mar mon, mar 3mon", "2025-02-01", "2025-03-03 2025-03-17"}, {"2024 mar3, mar17", "2025-03-01", "2025-03-03 2025-03-17"}, {"2024 mar, nov", "2025-03-01", "2025-03-31 2025-11-30"}, {"2024 w03, w-2", "2025-01-01", "2025-01-18 2025-12-27"}, {"2024 w03 mon, w-1 wed, w-01 sat", "2025-01-01", "2025-01-13 2025-12-31 2026-01-03"}, } for i, tt := range tests { t.Run(fmt.Sprintf("%03d %s %s", i, tt.date, tt.start), func(t *testing.T) { is := is.New(t) var date cal.Date _, err := date.Parse(tt.date) is.NoErr(err) start, err := time.Parse("2006-01-02", tt.start) is.NoErr(err) out := collectN(len(tt.out)+1, date.Project(start)) fields := strings.Fields(tt.out) is.Equal(len(out), len(fields)) for i, v := range fields { is.Equal(out[i].Format("2006-01-02"), v) } }) } } func collectN[T any](n int, seq iter.Seq[T]) []T { out := make([]T, 0, n) i := 0 for v := range seq { out = append(out, v) i++ if i == n { break } } return out } func timeDate(year, month, day int) time.Time { return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) }