diff --git a/types/time.go b/types/time.go index 5f6c9bff0f0c2..84ad2a69b66ef 100644 --- a/types/time.go +++ b/types/time.go @@ -1465,7 +1465,7 @@ func checkMonthDay(year, month, day int, allowInvalidDate bool) error { if month > 0 { maxDay = maxDaysInMonth[month-1] } - if month == 2 && year%4 != 0 { + if month == 2 && !isLeapYear(uint16(year)) { maxDay = 28 } } diff --git a/types/time_test.go b/types/time_test.go index e5a000efc0c46..7ca8b2b74624e 100644 --- a/types/time_test.go +++ b/types/time_test.go @@ -1342,3 +1342,43 @@ func (s *testTimeSuite) TestgetFracIndex(c *C) { c.Assert(index, Equals, testCase.expectIndex) } } + +func (s *testTimeSuite) TestCheckMonthDay(c *C) { + dates := []struct { + date types.MysqlTime + isValidDate bool + }{ + {types.FromDate(1900, 2, 29, 0, 0, 0, 0), false}, + {types.FromDate(1900, 2, 28, 0, 0, 0, 0), true}, + {types.FromDate(2000, 2, 29, 0, 0, 0, 0), true}, + {types.FromDate(2000, 1, 1, 0, 0, 0, 0), true}, + {types.FromDate(1900, 1, 1, 0, 0, 0, 0), true}, + {types.FromDate(1900, 1, 31, 0, 0, 0, 0), true}, + {types.FromDate(1900, 4, 1, 0, 0, 0, 0), true}, + {types.FromDate(1900, 4, 31, 0, 0, 0, 0), false}, + {types.FromDate(1900, 4, 30, 0, 0, 0, 0), true}, + {types.FromDate(2000, 2, 30, 0, 0, 0, 0), false}, + {types.FromDate(2000, 13, 1, 0, 0, 0, 0), false}, + {types.FromDate(4000, 2, 29, 0, 0, 0, 0), true}, + {types.FromDate(3200, 2, 29, 0, 0, 0, 0), true}, + } + + sc := &stmtctx.StatementContext{ + TimeZone: time.UTC, + AllowInvalidDate: false, + } + + for _, t := range dates { + tt := types.Time{ + Time: t.date, + Type: mysql.TypeDate, + Fsp: types.DefaultFsp, + } + err := tt.Check(sc) + if t.isValidDate { + c.Check(err, IsNil) + } else { + c.Check(types.ErrInvalidTimeFormat.Equal(err), IsTrue) + } + } +}