github.com/go-chrono/chrono@v0.0.0-20240102183611-532f0d0d7c34/local_date_test.go (about) 1 package chrono_test 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/go-chrono/chrono" 8 ) 9 10 func TestLocalDate(t *testing.T) { 11 for _, tt := range []struct { 12 year int 13 month chrono.Month 14 day int 15 weekday chrono.Weekday 16 isLeapYear bool 17 yearDay int 18 isoYear int 19 isoWeek int 20 }{ 21 {-4713, chrono.November, 24, chrono.Monday, false, 328, -4713, 48}, // 4714 BCE 22 {+5874898, chrono.June, 3, chrono.Tuesday, false, 154, +5874898, 23}, 23 {+1858, chrono.November, 17, chrono.Wednesday, false, 321, +1858, 46}, 24 {+1968, chrono.May, 24, chrono.Friday, true, 145, +1968, 21}, 25 {+1950, chrono.January, 1, chrono.Sunday, false, 1, +1949, 52}, 26 {+1958, chrono.January, 1, chrono.Wednesday, false, 1, +1958, 1}, 27 {+1582, chrono.October, 15, chrono.Friday, false, 288, +1582, 41}, 28 {+1, chrono.January, 1, chrono.Monday, false, 1, +1, 1}, 29 {+1970, chrono.January, 1, chrono.Thursday, false, 1, +1970, 1}, 30 {+200, chrono.March, 1, chrono.Saturday, false, 60, +200, 9}, 31 {+2020, chrono.December, 31, chrono.Thursday, true, 366, +2020, 53}, 32 {+2021, chrono.January, 1, chrono.Friday, false, 1, +2020, 53}, 33 {+2000, chrono.February, 29, chrono.Tuesday, true, 60, +2000, 9}, 34 {+2000, chrono.March, 1, chrono.Wednesday, true, 61, +2000, 9}, 35 } { 36 t.Run(fmt.Sprintf("%+05d-%02d-%02d", tt.year, tt.month, tt.day), func(t *testing.T) { 37 date := chrono.LocalDateOf(tt.year, tt.month, tt.day) 38 39 year, month, day := date.Date() 40 if year != tt.year { 41 t.Errorf("date.Date() year = %d, want %d", year, tt.year) 42 } 43 44 if month != tt.month { 45 t.Errorf("date.Date() month = %s, want %s", month, tt.month) 46 } 47 48 if day != tt.day { 49 t.Errorf("date.Date() day = %d, want %d", day, tt.day) 50 } 51 52 if weekday := date.Weekday(); weekday != tt.weekday { 53 t.Errorf("date.Weekday() = %s, want %s", weekday, tt.weekday) 54 } 55 56 if isLeapYear := date.IsLeapYear(); isLeapYear != tt.isLeapYear { 57 t.Errorf("date.YearDay() = %t, want %t", isLeapYear, tt.isLeapYear) 58 } 59 60 if yearDay := date.YearDay(); yearDay != tt.yearDay { 61 t.Errorf("date.YearDay() = %d, want %d", yearDay, tt.yearDay) 62 } 63 64 isoYear, isoWeek := date.ISOWeek() 65 if isoYear != tt.isoYear { 66 t.Errorf("date.ISOWeek() year = %d, want %d", isoYear, tt.isoYear) 67 } 68 69 if isoWeek != tt.isoWeek { 70 t.Errorf("date.ISOWeek() week = %d, want %d", isoWeek, tt.isoWeek) 71 } 72 }) 73 } 74 } 75 76 func TestLocalDateOf(t *testing.T) { 77 for _, tt := range []struct { 78 name string 79 year int 80 month chrono.Month 81 day int 82 }{ 83 {"year underflows", -4714, chrono.January, 1}, 84 {"year & month underflows", -4713, chrono.October, 1}, 85 {"year & month & day underflows", -4713, chrono.November, 23}, 86 {"year overflows", 5874899, chrono.January, 1}, 87 {"year & month overflows", 5874898, chrono.July, 1}, 88 {"year & month & day overflows", 5874898, chrono.June, 4}, 89 {"month underflows", 2001, 0, 1}, 90 {"month overflows", 2001, 13, 1}, 91 {"day underflows", 2001, chrono.February, 0}, 92 {"day overflows", 2001, chrono.February, 29}, 93 {"day overflows leap year", 2004, chrono.February, 30}, 94 } { 95 t.Run(tt.name, func(t *testing.T) { 96 func() { 97 defer func() { 98 if r := recover(); r == nil { 99 t.Error("expecting panic that didn't occur") 100 } 101 }() 102 103 chrono.LocalDateOf(tt.year, tt.month, tt.day) 104 }() 105 }) 106 } 107 } 108 109 func TestOfDayOfYear(t *testing.T) { 110 for _, tt := range []struct { 111 year int 112 day int 113 expected chrono.LocalDate 114 }{ 115 {2020, 60, chrono.LocalDateOf(2020, chrono.February, 29)}, 116 {2021, 60, chrono.LocalDateOf(2021, chrono.March, 1)}, 117 {2020, 120, chrono.LocalDateOf(2020, chrono.April, 29)}, 118 {2021, 120, chrono.LocalDateOf(2021, chrono.April, 30)}, 119 } { 120 t.Run(fmt.Sprintf("%04d-%03d", tt.year, tt.day), func(t *testing.T) { 121 if date := chrono.OfDayOfYear(tt.year, tt.day); date != tt.expected { 122 t.Errorf("OfDayOfYear(%d, %d) = %s, want %s", tt.year, tt.day, date, tt.expected) 123 } 124 }) 125 } 126 } 127 128 func TestOfFirstWeekday(t *testing.T) { 129 for _, tt := range []struct { 130 year int 131 month chrono.Month 132 weekday chrono.Weekday 133 expected chrono.LocalDate 134 }{ 135 {2020, chrono.January, chrono.Wednesday, chrono.LocalDateOf(2020, chrono.January, 1)}, 136 {2020, chrono.January, chrono.Monday, chrono.LocalDateOf(2020, chrono.January, 6)}, 137 {2020, chrono.March, chrono.Sunday, chrono.LocalDateOf(2020, chrono.March, 1)}, 138 } { 139 t.Run(fmt.Sprintf("%04d-%s %s", tt.year, tt.month, tt.weekday), func(t *testing.T) { 140 if date := chrono.OfFirstWeekday(tt.year, tt.month, tt.weekday); date != tt.expected { 141 t.Errorf("OfFirstWeekday(%d, %s, %s) = %s, want %s", tt.year, tt.month, tt.weekday, date, tt.expected) 142 } else if weekday := date.Weekday(); weekday != tt.weekday { 143 t.Errorf("weekday = %s, want %s", weekday, tt.weekday) 144 } 145 }) 146 } 147 } 148 149 func TestOfISOWeek(t *testing.T) { 150 for _, tt := range []struct { 151 isoYear int 152 isoWeek int 153 weekday chrono.Weekday 154 expected chrono.LocalDate 155 }{ 156 {1936, 51, chrono.Monday, chrono.LocalDateOf(1936, chrono.December, 14)}, 157 {1949, 52, chrono.Sunday, chrono.LocalDateOf(1950, chrono.January, 1)}, 158 {2020, 53, chrono.Friday, chrono.LocalDateOf(2021, chrono.January, 1)}, 159 } { 160 t.Run(fmt.Sprintf("%04d-W%02d-%d", tt.isoYear, tt.isoWeek, tt.weekday), func(t *testing.T) { 161 if date, err := chrono.OfISOWeek(tt.isoYear, tt.isoWeek, tt.weekday); err != nil { 162 t.Errorf("failed to calculate date from ISO week: %v", err) 163 } else if date != tt.expected { 164 t.Errorf("OfISOWeek(%d, %d, %s) = %s, want %s", tt.isoYear, tt.isoWeek, tt.weekday, date, tt.expected) 165 } 166 }) 167 } 168 } 169 170 func TestLocalDate_Date(t *testing.T) { 171 for _, tt := range []struct { 172 name string 173 date chrono.LocalDate 174 year int 175 month chrono.Month 176 day int 177 }{ 178 {"default value", chrono.LocalDate(0), 1970, chrono.January, 1}, 179 {"minimum value", chrono.MinLocalDate(), -4713, chrono.November, 24}, 180 {"maximum value", chrono.MaxLocalDate(), 5874898, chrono.June, 3}, 181 } { 182 t.Run(tt.name, func(t *testing.T) { 183 year, month, day := tt.date.Date() 184 if year != tt.year { 185 t.Errorf("date.Date() year = %d, want %d", year, tt.year) 186 } 187 188 if month != tt.month { 189 t.Errorf("date.Date() month = %s, want %s", month, tt.month) 190 } 191 192 if day != tt.day { 193 t.Errorf("date.Date() day = %d, want %d", day, tt.day) 194 } 195 }) 196 } 197 198 for _, tt := range []struct { 199 name string 200 date chrono.LocalDate 201 }{ 202 {"underflows", chrono.MinLocalDate() - 1}, 203 {"overflows", chrono.MaxLocalDate() + 1}, 204 } { 205 t.Run(tt.name, func(t *testing.T) { 206 func() { 207 defer func() { 208 if r := recover(); r == nil { 209 t.Error("expecting panic that didn't occur") 210 } 211 }() 212 213 tt.date.Date() 214 }() 215 }) 216 } 217 } 218 219 func TestLocalDate_AddDate(t *testing.T) { 220 for _, tt := range []struct { 221 name string 222 date chrono.LocalDate 223 addYears int 224 addMonths int 225 addDays int 226 expected chrono.LocalDate 227 }{ 228 {"nothing", chrono.LocalDateOf(2020, chrono.March, 18), 0, 0, 0, chrono.LocalDateOf(2020, chrono.March, 18)}, 229 {"add years", chrono.LocalDateOf(2020, chrono.March, 18), 105, 0, 0, chrono.LocalDateOf(2125, chrono.March, 18)}, 230 {"sub years", chrono.LocalDateOf(2020, chrono.March, 18), -280, 0, 0, chrono.LocalDateOf(1740, chrono.March, 18)}, 231 {"add months", chrono.LocalDateOf(2020, chrono.March, 18), 0, 6, 0, chrono.LocalDateOf(2020, chrono.September, 18)}, 232 {"sub months", chrono.LocalDateOf(2020, chrono.March, 18), 0, -2, 0, chrono.LocalDateOf(2020, chrono.January, 18)}, 233 {"add days", chrono.LocalDateOf(2020, chrono.March, 18), 0, 0, 8, chrono.LocalDateOf(2020, chrono.March, 26)}, 234 {"sub days", chrono.LocalDateOf(2020, chrono.March, 18), 0, 0, -15, chrono.LocalDateOf(2020, chrono.March, 3)}, 235 {"time package example", chrono.LocalDateOf(2011, chrono.January, 1), -1, 2, 3, chrono.LocalDateOf(2010, chrono.March, 4)}, 236 {"normalized time package example", chrono.LocalDateOf(2011, chrono.October, 31), 0, 1, 0, chrono.LocalDateOf(2011, chrono.December, 1)}, 237 {"wrap around day", chrono.LocalDateOf(2020, chrono.March, 18), 0, 0, 20, chrono.LocalDateOf(2020, chrono.April, 7)}, 238 } { 239 t.Run(tt.name, func(t *testing.T) { 240 if ok := tt.date.CanAddDate(tt.addYears, tt.addMonths, tt.addDays); !ok { 241 t.Errorf("date = %s, date.CanAdd(%d, %d, %d) = false, want true", tt.date, tt.addYears, tt.addMonths, tt.addDays) 242 } 243 244 if date := tt.date.AddDate(tt.addYears, tt.addMonths, tt.addDays); date != tt.expected { 245 t.Errorf("date = %s, date.Add(%d, %d, %d) = %s, want %s", tt.date, tt.addYears, tt.addMonths, tt.addDays, date, tt.expected) 246 } 247 }) 248 } 249 250 for _, tt := range []struct { 251 name string 252 date chrono.LocalDate 253 addDays int 254 }{ 255 {"underflow", chrono.MinLocalDate(), -1}, 256 {"overflow", chrono.MaxLocalDate(), 1}, 257 } { 258 t.Run(tt.name, func(t *testing.T) { 259 if ok := tt.date.CanAddDate(0, 0, tt.addDays); ok { 260 t.Errorf("date = %s, date.CanAdd(0, 0, %d) = true, want false", tt.date, tt.addDays) 261 } 262 263 func() { 264 defer func() { 265 if r := recover(); r == nil { 266 t.Error("expecting panic that didn't occur") 267 } 268 }() 269 270 tt.date.AddDate(0, 0, tt.addDays) 271 }() 272 }) 273 } 274 }