Skip to content

Commit

Permalink
Merge pull request #29 from pingcap/siddontang/update-time-codec
Browse files Browse the repository at this point in the history
mysqldef: save FSP and fix zone offset for codec
  • Loading branch information
siddontang committed Sep 7, 2015
2 parents ece2567 + 842721e commit d628bcb
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
31 changes: 28 additions & 3 deletions mysqldef/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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)
}
Expand All @@ -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.
Expand Down
21 changes: 21 additions & 0 deletions mysqldef/time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit d628bcb

Please sign in to comment.