Get rid of FracTime and friends
This commit is contained in:
parent
db67e68078
commit
83e16c72f2
@ -5,7 +5,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/localhots/bocadillo/mysql"
|
"github.com/localhots/bocadillo/mysql"
|
||||||
"github.com/localhots/bocadillo/tools"
|
"github.com/localhots/bocadillo/tools"
|
||||||
@ -191,8 +190,9 @@ func (e *RowsEvent) decodeValue(buf *tools.Buffer, ct mysql.ColumnType, meta uin
|
|||||||
buf.Skip(n)
|
buf.Skip(n)
|
||||||
return v
|
return v
|
||||||
case mysql.ColumnTypeTimestamp:
|
case mysql.ColumnTypeTimestamp:
|
||||||
ts := buf.ReadUint32()
|
v, n := mysql.DecodeTimestamp(buf.Cur(), meta)
|
||||||
return mysql.FracTime{Time: time.Unix(int64(ts), 0)}.String()
|
buf.Skip(n)
|
||||||
|
return v
|
||||||
case mysql.ColumnTypeTimestamp2:
|
case mysql.ColumnTypeTimestamp2:
|
||||||
v, n := mysql.DecodeTimestamp2(buf.Cur(), meta)
|
v, n := mysql.DecodeTimestamp2(buf.Cur(), meta)
|
||||||
buf.Skip(n)
|
buf.Skip(n)
|
||||||
|
@ -103,10 +103,17 @@ func DecodeTime2(data []byte, dec uint16) (string, int) {
|
|||||||
return fmt.Sprintf("%s%02d:%02d:%02d", sign, hour, minute, second), n
|
return fmt.Sprintf("%s%02d:%02d:%02d", sign, hour, minute, second), n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeTimestamp decodes TIMESTAMP value.
|
||||||
|
// Spec: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
|
||||||
|
// Implementation borrowed from https://github.com/siddontang/go-mysql/
|
||||||
|
func DecodeTimestamp(data []byte, dec uint16) (time.Time, int) {
|
||||||
|
return time.Unix(int64(DecodeUint32(data)), 0), 4
|
||||||
|
}
|
||||||
|
|
||||||
// DecodeTimestamp2 decodes TIMESTAMP v2 value.
|
// DecodeTimestamp2 decodes TIMESTAMP v2 value.
|
||||||
// Spec: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
|
// Spec: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
|
||||||
// Implementation borrowed from https://github.com/siddontang/go-mysql/
|
// Implementation borrowed from https://github.com/siddontang/go-mysql/
|
||||||
func DecodeTimestamp2(data []byte, dec uint16) (string, int) {
|
func DecodeTimestamp2(data []byte, dec uint16) (time.Time, int) {
|
||||||
// get timestamp binary length
|
// get timestamp binary length
|
||||||
n := int(4 + (dec+1)/2)
|
n := int(4 + (dec+1)/2)
|
||||||
sec := int64(binary.BigEndian.Uint32(data[0:4]))
|
sec := int64(binary.BigEndian.Uint32(data[0:4]))
|
||||||
@ -121,18 +128,18 @@ func DecodeTimestamp2(data []byte, dec uint16) (string, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if sec == 0 {
|
if sec == 0 {
|
||||||
return formatZeroTime(int(usec), int(dec)), n
|
return time.Time{}, n
|
||||||
}
|
}
|
||||||
|
|
||||||
return FracTime{time.Unix(sec, usec*1000), int(dec)}.String(), n
|
return time.Unix(sec, usec*1000), n
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeDatetime decodes DATETIME value.
|
// DecodeDatetime decodes DATETIME value.
|
||||||
// Spec: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
|
// Spec: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
|
||||||
func DecodeDatetime(v uint64) string {
|
func DecodeDatetime(v uint64) time.Time {
|
||||||
d := v / 1000000
|
d := v / 1000000
|
||||||
t := v % 1000000
|
t := v % 1000000
|
||||||
return FracTime{Time: time.Date(int(d/10000),
|
return time.Date(int(d/10000),
|
||||||
time.Month((d%10000)/100),
|
time.Month((d%10000)/100),
|
||||||
int(d%100),
|
int(d%100),
|
||||||
int(t/10000),
|
int(t/10000),
|
||||||
@ -140,13 +147,13 @@ func DecodeDatetime(v uint64) string {
|
|||||||
int(t%100),
|
int(t%100),
|
||||||
0,
|
0,
|
||||||
Timezone,
|
Timezone,
|
||||||
)}.String()
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeDatetime2 decodes DATETIME v2 value.
|
// DecodeDatetime2 decodes DATETIME v2 value.
|
||||||
// Spec: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
|
// Spec: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
|
||||||
// Implementation borrowed from https://github.com/siddontang/go-mysql/
|
// Implementation borrowed from https://github.com/siddontang/go-mysql/
|
||||||
func DecodeDatetime2(data []byte, dec uint16) (string, int) {
|
func DecodeDatetime2(data []byte, dec uint16) (time.Time, int) {
|
||||||
const offset int64 = 0x8000000000
|
const offset int64 = 0x8000000000
|
||||||
// get datetime binary length
|
// get datetime binary length
|
||||||
n := int(5 + (dec+1)/2)
|
n := int(5 + (dec+1)/2)
|
||||||
@ -164,7 +171,7 @@ func DecodeDatetime2(data []byte, dec uint16) (string, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if intPart == 0 {
|
if intPart == 0 {
|
||||||
return formatZeroTime(int(frac), int(dec)), n
|
return time.Time{}, n
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp := intPart<<24 + frac
|
tmp := intPart<<24 + frac
|
||||||
@ -188,41 +195,5 @@ func DecodeDatetime2(data []byte, dec uint16) (string, int) {
|
|||||||
minute := int((hms >> 6) % (1 << 6))
|
minute := int((hms >> 6) % (1 << 6))
|
||||||
hour := int((hms >> 12))
|
hour := int((hms >> 12))
|
||||||
|
|
||||||
return FracTime{time.Date(year, time.Month(month), day, hour, minute, second, int(frac*1000), Timezone), int(dec)}.String(), n
|
return time.Date(year, time.Month(month), day, hour, minute, second, int(frac*1000), Timezone), n
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
fracTimeFormat = [...]string{
|
|
||||||
"2006-01-02T15:04:05Z",
|
|
||||||
"2006-01-02T15:04:05.0Z",
|
|
||||||
"2006-01-02T15:04:05.00Z",
|
|
||||||
"2006-01-02T15:04:05.000Z",
|
|
||||||
"2006-01-02T15:04:05.0000Z",
|
|
||||||
"2006-01-02T15:04:05.00000Z",
|
|
||||||
"2006-01-02T15:04:05.000000Z",
|
|
||||||
}
|
|
||||||
zeroTimes = [...]string{
|
|
||||||
"0000-00-00T00:00:00Z",
|
|
||||||
"0000-00-00T00:00:00.0Z",
|
|
||||||
"0000-00-00T00:00:00.00Z",
|
|
||||||
"0000-00-00T00:00:00.000Z",
|
|
||||||
"0000-00-00T00:00:00.0000Z",
|
|
||||||
"0000-00-00T00:00:00.00000Z",
|
|
||||||
"0000-00-00T00:00:00.000000Z",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// FracTime is a help structure wrapping Golang Time.
|
|
||||||
type FracTime struct {
|
|
||||||
time.Time
|
|
||||||
Dec int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t FracTime) String() string {
|
|
||||||
return t.Format(fracTimeFormat[t.Dec])
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatZeroTime(frac int, dec int) string {
|
|
||||||
// We are going to ignore frac/dec distinction here
|
|
||||||
return zeroTimes[dec]
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package tests
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/localhots/bocadillo/mysql"
|
"github.com/localhots/bocadillo/mysql"
|
||||||
)
|
)
|
||||||
@ -61,96 +62,96 @@ func TestTimestamp(t *testing.T) {
|
|||||||
tbl := suite.createTable(mysql.ColumnTypeTimestamp, "", attrNone)
|
tbl := suite.createTable(mysql.ColumnTypeTimestamp, "", attrNone)
|
||||||
defer tbl.drop(t)
|
defer tbl.drop(t)
|
||||||
|
|
||||||
vals := []string{
|
vals := []time.Time{
|
||||||
"0000-00-00T00:00:00Z",
|
parseTime("0000-00-00T00:00:00Z"),
|
||||||
// This is the lowest I could get
|
// This is the lowest I could get
|
||||||
// Spec says 1970-01-01 00:00:01 should be supported
|
// Spec says 1970-01-01 00:00:01 should be supported
|
||||||
"1970-01-01T01:00:01Z",
|
parseTime("1970-01-01T01:00:01Z"),
|
||||||
"1975-01-01T00:00:01Z",
|
parseTime("1975-01-01T00:00:01Z"),
|
||||||
"1985-01-01T00:00:01Z",
|
parseTime("1985-01-01T00:00:01Z"),
|
||||||
"1999-12-31T23:59:59Z",
|
parseTime("1999-12-31T23:59:59Z"),
|
||||||
"2018-11-08T19:26:00Z",
|
parseTime("2018-11-08T19:26:00Z"),
|
||||||
"2038-01-19T03:14:07Z",
|
parseTime("2038-01-19T03:14:07Z"),
|
||||||
"2038-01-19T04:14:07Z", // Should be outside supported range? 2038-01-19 03:14:07
|
parseTime("2038-01-19T04:14:07Z"), // Should be outside supported range? 2038-01-19 03:14:07
|
||||||
}
|
}
|
||||||
for _, v := range vals {
|
for _, v := range vals {
|
||||||
t.Run(v, func(t *testing.T) {
|
t.Run(v.Format(time.RFC3339Nano), func(t *testing.T) {
|
||||||
suite.insertAndCompare(t, tbl, v)
|
suite.insertAndCompare(t, tbl, v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDatetime(t *testing.T) {
|
func TestDatetime(t *testing.T) {
|
||||||
inputs := map[string][]string{
|
inputs := map[string][]time.Time{
|
||||||
"0": {
|
"0": {
|
||||||
"0000-00-00T00:00:00Z",
|
parseTime("0000-00-00T00:00:00Z"),
|
||||||
"1000-01-01T00:00:00Z",
|
parseTime("1000-01-01T00:00:00Z"),
|
||||||
"1975-01-01T00:00:01Z",
|
parseTime("1975-01-01T00:00:01Z"),
|
||||||
"1985-01-01T00:00:01Z",
|
parseTime("1985-01-01T00:00:01Z"),
|
||||||
"1999-12-31T23:59:59Z",
|
parseTime("1999-12-31T23:59:59Z"),
|
||||||
"2018-11-08T19:26:00Z",
|
parseTime("2018-11-08T19:26:00Z"),
|
||||||
"2038-01-19T03:14:07Z",
|
parseTime("2038-01-19T03:14:07Z"),
|
||||||
"9999-12-31T23:59:59Z",
|
parseTime("9999-12-31T23:59:59Z"),
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"0000-00-00T00:00:00.0Z",
|
parseTime("0000-00-00T00:00:00.0Z"),
|
||||||
"1000-01-01T00:00:00.1Z",
|
parseTime("1000-01-01T00:00:00.1Z"),
|
||||||
"1975-01-01T00:00:01.1Z",
|
parseTime("1975-01-01T00:00:01.1Z"),
|
||||||
"1985-01-01T00:00:01.1Z",
|
parseTime("1985-01-01T00:00:01.1Z"),
|
||||||
"1999-12-31T23:59:59.1Z",
|
parseTime("1999-12-31T23:59:59.1Z"),
|
||||||
"2018-11-08T19:26:00.1Z",
|
parseTime("2018-11-08T19:26:00.1Z"),
|
||||||
"2038-01-19T03:14:07.1Z",
|
parseTime("2038-01-19T03:14:07.1Z"),
|
||||||
"9999-12-31T23:59:59.1Z",
|
parseTime("9999-12-31T23:59:59.1Z"),
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"0000-00-00T00:00:00.00Z",
|
parseTime("0000-00-00T00:00:00.00Z"),
|
||||||
"1000-01-01T00:00:00.22Z",
|
parseTime("1000-01-01T00:00:00.22Z"),
|
||||||
"1975-01-01T00:00:01.22Z",
|
parseTime("1975-01-01T00:00:01.22Z"),
|
||||||
"1985-01-01T00:00:01.22Z",
|
parseTime("1985-01-01T00:00:01.22Z"),
|
||||||
"1999-12-31T23:59:59.22Z",
|
parseTime("1999-12-31T23:59:59.22Z"),
|
||||||
"2018-11-08T19:26:00.22Z",
|
parseTime("2018-11-08T19:26:00.22Z"),
|
||||||
"2038-01-19T03:14:07.22Z",
|
parseTime("2038-01-19T03:14:07.22Z"),
|
||||||
"9999-12-31T23:59:59.22Z",
|
parseTime("9999-12-31T23:59:59.22Z"),
|
||||||
},
|
},
|
||||||
"3": {
|
"3": {
|
||||||
"0000-00-00T00:00:00.000Z",
|
parseTime("0000-00-00T00:00:00.000Z"),
|
||||||
"1000-01-01T00:00:00.333Z",
|
parseTime("1000-01-01T00:00:00.333Z"),
|
||||||
"1975-01-01T00:00:01.333Z",
|
parseTime("1975-01-01T00:00:01.333Z"),
|
||||||
"1985-01-01T00:00:01.333Z",
|
parseTime("1985-01-01T00:00:01.333Z"),
|
||||||
"1999-12-31T23:59:59.333Z",
|
parseTime("1999-12-31T23:59:59.333Z"),
|
||||||
"2018-11-08T19:26:00.333Z",
|
parseTime("2018-11-08T19:26:00.333Z"),
|
||||||
"2038-01-19T03:14:07.333Z",
|
parseTime("2038-01-19T03:14:07.333Z"),
|
||||||
"9999-12-31T23:59:59.333Z",
|
parseTime("9999-12-31T23:59:59.333Z"),
|
||||||
},
|
},
|
||||||
"4": {
|
"4": {
|
||||||
"0000-00-00T00:00:00.0000Z",
|
parseTime("0000-00-00T00:00:00.0000Z"),
|
||||||
"1000-01-01T00:00:00.4444Z",
|
parseTime("1000-01-01T00:00:00.4444Z"),
|
||||||
"1975-01-01T00:00:01.4444Z",
|
parseTime("1975-01-01T00:00:01.4444Z"),
|
||||||
"1985-01-01T00:00:01.4444Z",
|
parseTime("1985-01-01T00:00:01.4444Z"),
|
||||||
"1999-12-31T23:59:59.4444Z",
|
parseTime("1999-12-31T23:59:59.4444Z"),
|
||||||
"2018-11-08T19:26:00.4444Z",
|
parseTime("2018-11-08T19:26:00.4444Z"),
|
||||||
"2038-01-19T03:14:07.4444Z",
|
parseTime("2038-01-19T03:14:07.4444Z"),
|
||||||
"9999-12-31T23:59:59.4444Z",
|
parseTime("9999-12-31T23:59:59.4444Z"),
|
||||||
},
|
},
|
||||||
"5": {
|
"5": {
|
||||||
"0000-00-00T00:00:00.00000Z",
|
parseTime("0000-00-00T00:00:00.00000Z"),
|
||||||
"1000-01-01T00:00:00.55555Z",
|
parseTime("1000-01-01T00:00:00.55555Z"),
|
||||||
"1975-01-01T00:00:01.55555Z",
|
parseTime("1975-01-01T00:00:01.55555Z"),
|
||||||
"1985-01-01T00:00:01.55555Z",
|
parseTime("1985-01-01T00:00:01.55555Z"),
|
||||||
"1999-12-31T23:59:59.55555Z",
|
parseTime("1999-12-31T23:59:59.55555Z"),
|
||||||
"2018-11-08T19:26:00.55555Z",
|
parseTime("2018-11-08T19:26:00.55555Z"),
|
||||||
"2038-01-19T03:14:07.55555Z",
|
parseTime("2038-01-19T03:14:07.55555Z"),
|
||||||
"9999-12-31T23:59:59.55555Z",
|
parseTime("9999-12-31T23:59:59.55555Z"),
|
||||||
},
|
},
|
||||||
"6": {
|
"6": {
|
||||||
"0000-00-00T00:00:00.000000Z",
|
parseTime("0000-00-00T00:00:00.000000Z"),
|
||||||
"1000-01-01T00:00:00.666666Z",
|
parseTime("1000-01-01T00:00:00.666666Z"),
|
||||||
"1975-01-01T00:00:01.666666Z",
|
parseTime("1975-01-01T00:00:01.666666Z"),
|
||||||
"1985-01-01T00:00:01.666666Z",
|
parseTime("1985-01-01T00:00:01.666666Z"),
|
||||||
"1999-12-31T23:59:59.666666Z",
|
parseTime("1999-12-31T23:59:59.666666Z"),
|
||||||
"2018-11-08T19:26:00.666666Z",
|
parseTime("2018-11-08T19:26:00.666666Z"),
|
||||||
"2038-01-19T03:14:07.666666Z",
|
parseTime("2038-01-19T03:14:07.666666Z"),
|
||||||
"9999-12-31T23:59:59.666666Z",
|
parseTime("9999-12-31T23:59:59.666666Z"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for length, vals := range inputs {
|
for length, vals := range inputs {
|
||||||
@ -159,10 +160,15 @@ func TestDatetime(t *testing.T) {
|
|||||||
defer tbl.drop(t)
|
defer tbl.drop(t)
|
||||||
|
|
||||||
for _, v := range vals {
|
for _, v := range vals {
|
||||||
t.Run(v, func(t *testing.T) {
|
t.Run(v.Format(time.RFC3339Nano), func(t *testing.T) {
|
||||||
suite.insertAndCompare(t, tbl, v)
|
suite.insertAndCompare(t, tbl, v)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseTime(str string) time.Time {
|
||||||
|
t, _ := time.Parse(str, time.RFC3339Nano)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user