diff --git a/mysqldef/time.go b/mysqldef/time.go index cbf627695866b..4eb4e341d81b8 100644 --- a/mysqldef/time.go +++ b/mysqldef/time.go @@ -143,7 +143,10 @@ func (t Time) Marshal() ([]byte, error) { switch t.Type { case TypeDatetime, TypeDate: - _, offset := time.Now().Zone() + // We must use t's Zone not current Now Zone, + // For EDT/EST, even we create the time with time.Local location, + // we may still have a different zone with current Now time. + _, offset := t.Zone() // For datetime and date type, we have a trick to marshal. // e.g, if local time is 2010-10-10T10:10:10 UTC+8 // we will change this to 2010-10-10T10:10:10 UTC and then marshal. @@ -154,7 +157,14 @@ func (t Time) Marshal() ([]byte, error) { err = errors.Errorf("invalid time type %d", t.Type) } - return b, err + if err != nil { + return nil, errors.Trace(err) + } + + // append fsp to the end + b = append(b, byte(t.Fsp)) + + return b, nil } // Unmarshal decodes the binary data into Time with current local time. @@ -165,6 +175,20 @@ func (t *Time) Unmarshal(b []byte) error { // UnmarshalInLocation decodes the binary data // into Time with a specific time Location. func (t *Time) UnmarshalInLocation(b []byte, loc *time.Location) error { + if len(b) < 1 { + return errors.Errorf("insufficient bytes to unmarshal time") + } + + // Get fsp + fsp, err := checkFsp(int(int8(b[len(b)-1]))) + if err != nil { + return errors.Trace(err) + } + + t.Fsp = fsp + + b = b[:len(b)-1] + if err := t.Time.UnmarshalBinary(b); err != nil { return errors.Trace(err) } @@ -175,7 +199,8 @@ func (t *Time) UnmarshalInLocation(b []byte, loc *time.Location) error { if t.Type == TypeDatetime || t.Type == TypeDate { // e.g, for 2010-10-10T10:10:10 UTC, we will unmarshal to 2010-10-10T10:10:10 location - _, offset := time.Now().In(loc).Zone() + _, offset := t.Time.In(loc).Zone() + t.Time = t.Time.Add(-time.Duration(offset) * time.Second).In(loc) if t.Type == TypeDate { // for date type ,we will only use year, month and day. diff --git a/mysqldef/time_test.go b/mysqldef/time_test.go index e69264cb78ad4..c4e158648377e 100644 --- a/mysqldef/time_test.go +++ b/mysqldef/time_test.go @@ -337,6 +337,27 @@ func (s *testTimeSuite) TestCodec(c *C) { err = t4.Unmarshal(b) c.Assert(err, IsNil) c.Assert(t.String(), Equals, t4.String()) + + tbl := []string{ + "2000-01-01 00:00:00.000000", + "2000-01-01 00:00:00.123456", + "0001-01-01 00:00:00.123456", + "2000-06-01 00:00:00.999999", + } + + for _, test := range tbl { + t, err := ParseTime(test, TypeDatetime, MaxFsp) + c.Assert(err, IsNil) + + b, err := t.Marshal() + c.Assert(err, IsNil) + + var dest Time + dest.Type = TypeDatetime + err = dest.Unmarshal(b) + c.Assert(err, IsNil) + c.Assert(dest.String(), Equals, test) + } } func (s *testTimeSuite) TestParseTimeFromNum(c *C) {