Fix loc parsing

This commit is contained in:
mix3 2015-03-05 11:05:58 +09:00 committed by Yasuhiro Matsumoto
parent 71712f0ba9
commit e48e0597ab
2 changed files with 33 additions and 29 deletions

View File

@ -267,20 +267,26 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
} }
var loc *time.Location var loc *time.Location
if u, err := url.Parse(dsn); err == nil { pos := strings.IndexRune(dsn, '?')
for k, v := range u.Query() { if pos >= 1 {
switch k { params, err := url.ParseQuery(dsn[pos+1:])
case "loc": if err != nil {
if len(v) > 0 { return nil, err
if v[0] == "auto" {
v[0] = time.Local.String()
}
if loc, err = time.LoadLocation(v[0]); err != nil {
return nil, fmt.Errorf("Invalid loc: %v: %v", v[0], err)
} }
// loc
if val := params.Get("loc"); val != "" {
if val == "auto" {
loc = time.Local
} else {
loc, err = time.LoadLocation(val)
if err != nil {
return nil, fmt.Errorf("Invalid loc: %v: %v", val, err)
} }
} }
} }
dsn = dsn[:pos-1]
} }
var db *C.sqlite3 var db *C.sqlite3
@ -525,24 +531,21 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error {
switch rc.decltype[i] { switch rc.decltype[i] {
case "timestamp", "datetime", "date": case "timestamp", "datetime", "date":
unixTimestamp := strconv.FormatInt(val, 10) unixTimestamp := strconv.FormatInt(val, 10)
var t time.Time
if len(unixTimestamp) == 13 { if len(unixTimestamp) == 13 {
duration, err := time.ParseDuration(unixTimestamp + "ms") duration, err := time.ParseDuration(unixTimestamp + "ms")
if err != nil { if err != nil {
return fmt.Errorf("error parsing %s value %d, %s", rc.decltype[i], val, err) return fmt.Errorf("error parsing %s value %d, %s", rc.decltype[i], val, err)
} }
epoch := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC) epoch := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC)
t = epoch.Add(duration)
} else {
t = time.Unix(val, 0)
}
if rc.s.c.loc != nil { if rc.s.c.loc != nil {
dest[i] = epoch.Add(duration).In(rc.s.c.loc) t = t.In(rc.s.c.loc)
} else {
dest[i] = epoch.Add(duration)
}
} else {
if rc.s.c.loc != nil {
dest[i] = time.Unix(val, 0).In(rc.s.c.loc)
} else {
dest[i] = time.Unix(val, 0)
}
} }
dest[i] = t
case "boolean": case "boolean":
dest[i] = val > 0 dest[i] = val > 0
default: default:
@ -574,20 +577,21 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error {
switch rc.decltype[i] { switch rc.decltype[i] {
case "timestamp", "datetime", "date": case "timestamp", "datetime", "date":
var t time.Time
for _, format := range SQLiteTimestampFormats { for _, format := range SQLiteTimestampFormats {
if timeVal, err = time.ParseInLocation(format, s, time.UTC); err == nil { if timeVal, err = time.ParseInLocation(format, s, time.UTC); err == nil {
if rc.s.c.loc != nil { t = timeVal
dest[i] = timeVal.In(rc.s.c.loc)
} else {
dest[i] = timeVal
}
break break
} }
} }
if err != nil { if err != nil {
// The column is a time value, so return the zero time on parse failure. // The column is a time value, so return the zero time on parse failure.
dest[i] = time.Time{} t = time.Time{}
} }
if rc.s.c.loc != nil {
t = t.In(rc.s.c.loc)
}
dest[i] = t
default: default:
dest[i] = []byte(s) dest[i] = []byte(s)
} }

View File

@ -719,10 +719,10 @@ func TestTimezoneConversion(t *testing.T) {
t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt)
} }
if tests[id].expected.Location().String() != ts.Location().String() { if tests[id].expected.Location().String() != ts.Location().String() {
t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].expected.Location().String(), ts.Location().String()) t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected.Location().String(), ts.Location().String())
} }
if tests[id].expected.Location().String() != dt.Location().String() { if tests[id].expected.Location().String() != dt.Location().String() {
t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].expected.Location().String(), dt.Location().String()) t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected.Location().String(), dt.Location().String())
} }
} }