types: Fix potential timezone related bugs caused by gotime.Local (#13833)

This commit is contained in:
Rustin
2019-12-20 22:38:25 +08:00
committed by lysu
parent 1d60894c96
commit 4d4678a4dd
5 changed files with 39 additions and 25 deletions

View File

@ -26,6 +26,7 @@ import (
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/types/json"
"github.com/pingcap/tidb/util/chunk"
"github.com/pingcap/tidb/util/mock"
"github.com/pingcap/tidb/util/testleak"
)
@ -163,7 +164,13 @@ func (s *testUtilSuite) TestDumpTextValue(c *C) {
var d types.Datum
time, err := types.ParseTime(nil, "2017-01-05 23:59:59.575601", mysql.TypeDatetime, 0)
sc := mock.NewContext().GetSessionVars().StmtCtx
sc.IgnoreZeroInDate = true
losAngelesTz, err := time.LoadLocation("America/Los_Angeles")
c.Assert(err, IsNil)
sc.TimeZone = losAngelesTz
time, err := types.ParseTime(sc, "2017-01-05 23:59:59.575601", mysql.TypeDatetime, 0)
c.Assert(err, IsNil)
d.SetMysqlTime(time)
columns[0].Type = mysql.TypeDatetime
@ -171,7 +178,7 @@ func (s *testUtilSuite) TestDumpTextValue(c *C) {
c.Assert(err, IsNil)
c.Assert(mustDecodeStr(c, bs), Equals, "2017-01-06 00:00:00")
duration, err := types.ParseDuration(nil, "11:30:45", 0)
duration, err := types.ParseDuration(sc, "11:30:45", 0)
c.Assert(err, IsNil)
d.SetMysqlDuration(duration)
columns[0].Type = mysql.TypeDuration

View File

@ -155,15 +155,15 @@ func (s *testTypeConvertSuite) TestConvertType(c *C) {
vv, err := Convert(v, ft)
c.Assert(err, IsNil)
c.Assert(vv.(Duration).String(), Equals, "10:11:12.1")
vd, err := ParseTime(nil, "2010-10-10 10:11:11.12345", mysql.TypeDatetime, 2)
sc := &stmtctx.StatementContext{TimeZone: time.UTC}
vd, err := ParseTime(sc, "2010-10-10 10:11:11.12345", mysql.TypeDatetime, 2)
c.Assert(vd.String(), Equals, "2010-10-10 10:11:11.12")
c.Assert(err, IsNil)
v, err = Convert(vd, ft)
c.Assert(err, IsNil)
c.Assert(v.(Duration).String(), Equals, "10:11:11.1")
vt, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, "2010-10-10 10:11:11.12345", mysql.TypeTimestamp, 2)
vt, err := ParseTime(sc, "2010-10-10 10:11:11.12345", mysql.TypeTimestamp, 2)
c.Assert(vt.String(), Equals, "2010-10-10 10:11:11.12")
c.Assert(err, IsNil)
v, err = Convert(vt, ft)
@ -249,7 +249,6 @@ func (s *testTypeConvertSuite) TestConvertType(c *C) {
// Test Datum.ToDecimal with bad number.
d := NewDatum("hello")
sc := new(stmtctx.StatementContext)
_, err = d.ToDecimal(sc)
c.Assert(terror.ErrorEqual(err, ErrBadNumber), IsTrue, Commentf("err %v", err))

View File

@ -824,7 +824,7 @@ func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int8, isFloat b
tmp := FromDate(year, month, day, hour, minute, second, microsecond)
if overflow {
// Convert to Go time and add 1 second, to handle input like 2017-01-05 08:40:59.575601
t1, err := tmp.GoTime(gotime.Local)
t1, err := tmp.GoTime(sc.TimeZone)
if err != nil {
return ZeroDatetime, errors.Trace(err)
}

View File

@ -491,7 +491,7 @@ func (s *testTimeSuite) TestCodec(c *C) {
}
for _, test := range tbl {
t, err := types.ParseTime(nil, test, mysql.TypeDatetime, types.MaxFsp)
t, err := types.ParseTime(sc, test, mysql.TypeDatetime, types.MaxFsp)
c.Assert(err, IsNil)
packed, _ = t.ToPackedUint()
@ -582,6 +582,9 @@ func (s *testTimeSuite) TestParseTimeFromNum(c *C) {
func (s *testTimeSuite) TestToNumber(c *C) {
sc := mock.NewContext().GetSessionVars().StmtCtx
sc.IgnoreZeroInDate = true
losAngelesTz, err := time.LoadLocation("America/Los_Angeles")
c.Assert(err, IsNil)
sc.TimeZone = losAngelesTz
defer testleak.AfterTest(c)()
tblDateTime := []struct {
Input string
@ -600,7 +603,7 @@ func (s *testTimeSuite) TestToNumber(c *C) {
}
for _, test := range tblDateTime {
t, err := types.ParseTime(nil, test.Input, mysql.TypeDatetime, test.Fsp)
t, err := types.ParseTime(sc, test.Input, mysql.TypeDatetime, test.Fsp)
c.Assert(err, IsNil)
c.Assert(t.ToNumber().String(), Equals, test.Expect)
}
@ -623,7 +626,7 @@ func (s *testTimeSuite) TestToNumber(c *C) {
}
for _, test := range tblDate {
t, err := types.ParseTime(nil, test.Input, mysql.TypeDate, 0)
t, err := types.ParseTime(sc, test.Input, mysql.TypeDate, 0)
c.Assert(err, IsNil)
c.Assert(t.ToNumber().String(), Equals, test.Expect)
}
@ -721,7 +724,8 @@ func (s *testTimeSuite) TestRoundFrac(c *C) {
c.Assert(nv.String(), Equals, t.Except)
}
// test different time zone
losAngelesTz, _ := time.LoadLocation("America/Los_Angeles")
losAngelesTz, err := time.LoadLocation("America/Los_Angeles")
c.Assert(err, IsNil)
sc.TimeZone = losAngelesTz
tbl = []struct {
Input string
@ -783,6 +787,10 @@ func (s *testTimeSuite) TestRoundFrac(c *C) {
}
func (s *testTimeSuite) TestConvert(c *C) {
sc := mock.NewContext().GetSessionVars().StmtCtx
sc.IgnoreZeroInDate = true
losAngelesTz, _ := time.LoadLocation("America/Los_Angeles")
sc.TimeZone = losAngelesTz
defer testleak.AfterTest(c)()
tbl := []struct {
Input string
@ -799,7 +807,7 @@ func (s *testTimeSuite) TestConvert(c *C) {
}
for _, t := range tbl {
v, err := types.ParseTime(nil, t.Input, mysql.TypeDatetime, t.Fsp)
v, err := types.ParseTime(sc, t.Input, mysql.TypeDatetime, t.Fsp)
c.Assert(err, IsNil)
nv, err := v.ConvertToDuration()
c.Assert(err, IsNil)
@ -815,23 +823,22 @@ func (s *testTimeSuite) TestConvert(c *C) {
{"11:30:45.123456", 0},
{"1 11:30:45.999999", 0},
}
sc := mock.NewContext().GetSessionVars().StmtCtx
// test different time zone.
sc.TimeZone = time.UTC
for _, t := range tblDuration {
v, err := types.ParseDuration(sc, t.Input, t.Fsp)
c.Assert(err, IsNil)
year, month, day := time.Now().In(time.UTC).Date()
n := time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
year, month, day := time.Now().In(sc.TimeZone).Date()
n := time.Date(year, month, day, 0, 0, 0, 0, sc.TimeZone)
t, err := v.ConvertToTime(sc, mysql.TypeDatetime)
c.Assert(err, IsNil)
// TODO: Consider time_zone variable.
t1, _ := t.Time.GoTime(time.UTC)
t1, _ := t.Time.GoTime(sc.TimeZone)
c.Assert(t1.Sub(n), Equals, v.Duration)
}
}
func (s *testTimeSuite) TestCompare(c *C) {
sc := &stmtctx.StatementContext{TimeZone: time.UTC}
defer testleak.AfterTest(c)()
tbl := []struct {
Arg1 string
@ -846,7 +853,7 @@ func (s *testTimeSuite) TestCompare(c *C) {
}
for _, t := range tbl {
v1, err := types.ParseTime(nil, t.Arg1, mysql.TypeDatetime, types.MaxFsp)
v1, err := types.ParseTime(sc, t.Arg1, mysql.TypeDatetime, types.MaxFsp)
c.Assert(err, IsNil)
ret, err := v1.CompareString(nil, t.Arg2)
@ -854,7 +861,7 @@ func (s *testTimeSuite) TestCompare(c *C) {
c.Assert(ret, Equals, t.Ret)
}
v1, err := types.ParseTime(nil, "2011-10-10 11:11:11", mysql.TypeDatetime, types.MaxFsp)
v1, err := types.ParseTime(sc, "2011-10-10 11:11:11", mysql.TypeDatetime, types.MaxFsp)
c.Assert(err, IsNil)
res, err := v1.CompareString(nil, "Test should error")
c.Assert(err, NotNil)
@ -1015,11 +1022,11 @@ func (s *testTimeSuite) TestTimeAdd(c *C) {
TimeZone: time.UTC,
}
for _, t := range tbl {
v1, err := types.ParseTime(nil, t.Arg1, mysql.TypeDatetime, types.MaxFsp)
v1, err := types.ParseTime(sc, t.Arg1, mysql.TypeDatetime, types.MaxFsp)
c.Assert(err, IsNil)
dur, err := types.ParseDuration(sc, t.Arg2, types.MaxFsp)
c.Assert(err, IsNil)
result, err := types.ParseTime(nil, t.Ret, mysql.TypeDatetime, types.MaxFsp)
result, err := types.ParseTime(sc, t.Ret, mysql.TypeDatetime, types.MaxFsp)
c.Assert(err, IsNil)
v2, err := v1.Add(sc, dur)
c.Assert(err, IsNil)
@ -1652,9 +1659,9 @@ func (s *testTimeSuite) TestTimeSub(c *C) {
TimeZone: time.UTC,
}
for _, t := range tbl {
v1, err := types.ParseTime(nil, t.Arg1, mysql.TypeDatetime, types.MaxFsp)
v1, err := types.ParseTime(sc, t.Arg1, mysql.TypeDatetime, types.MaxFsp)
c.Assert(err, IsNil)
v2, err := types.ParseTime(nil, t.Arg2, mysql.TypeDatetime, types.MaxFsp)
v2, err := types.ParseTime(sc, t.Arg2, mysql.TypeDatetime, types.MaxFsp)
c.Assert(err, IsNil)
dur, err := types.ParseDuration(sc, t.Ret, types.MaxFsp)
c.Assert(err, IsNil)

View File

@ -530,7 +530,8 @@ func (s *testCodecSuite) TestBytes(c *C) {
}
func parseTime(c *C, s string) types.Time {
m, err := types.ParseTime(nil, s, mysql.TypeDatetime, types.DefaultFsp)
sc := &stmtctx.StatementContext{TimeZone: time.UTC}
m, err := types.ParseTime(sc, s, mysql.TypeDatetime, types.DefaultFsp)
c.Assert(err, IsNil)
return m
}