mirror of
https://github.com/glebarez/go-sqlite.git
synced 2025-10-04 15:32:46 +08:00
driver: support scanning more formats into time.Time
Fixes https://gitlab.com/cznic/sqlite/-/issues/46
This commit is contained in:
51
all_test.go
51
all_test.go
@@ -1127,6 +1127,57 @@ func TestTime(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// https://gitlab.com/cznic/sqlite/-/issues/46
|
||||
func TestTimeScan(t *testing.T) {
|
||||
ref := time.Date(2021, 1, 2, 16, 39, 17, 123456789, time.UTC)
|
||||
|
||||
cases := []struct {
|
||||
s string
|
||||
w time.Time
|
||||
}{
|
||||
{s: "2021-01-02 12:39:17 -0400 ADT m=+00000", w: ref.Truncate(time.Second)},
|
||||
{s: "2021-01-02 16:39:17 +0000 UTC m=+0.000000001", w: ref.Truncate(time.Second)},
|
||||
{s: "2021-01-02 12:39:17.123456 -0400 ADT m=+00000", w: ref.Truncate(time.Microsecond)},
|
||||
{s: "2021-01-02 16:39:17.123456 +0000 UTC m=+0.000000001", w: ref.Truncate(time.Microsecond)},
|
||||
{s: "2021-01-02 16:39:17Z", w: ref.Truncate(time.Second)},
|
||||
{s: "2021-01-02 16:39:17+00:00", w: ref.Truncate(time.Second)},
|
||||
{s: "2021-01-02T16:39:17.123456+00:00", w: ref.Truncate(time.Microsecond)},
|
||||
{s: "2021-01-02 16:39:17.123456+00:00", w: ref.Truncate(time.Microsecond)},
|
||||
{s: "2021-01-02 12:39:17-04:00", w: ref.Truncate(time.Second)},
|
||||
{s: "2021-01-02 16:39:17", w: ref.Truncate(time.Second)},
|
||||
{s: "2021-01-02T16:39:17", w: ref.Truncate(time.Second)},
|
||||
{s: "2021-01-02 16:39", w: ref.Truncate(time.Minute)},
|
||||
{s: "2021-01-02T16:39", w: ref.Truncate(time.Minute)},
|
||||
{s: "2021-01-02", w: ref.Truncate(24 * time.Hour)},
|
||||
}
|
||||
|
||||
db, err := sql.Open(driverName, "file::memory:")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
for _, colType := range []string{"DATE", "DATETIME", "TIMESTAMP"} {
|
||||
for _, tc := range cases {
|
||||
if _, err := db.Exec("drop table if exists x; create table x (y " + colType + ")"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := db.Exec("insert into x (y) values (?)", tc.s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var got time.Time
|
||||
|
||||
if err := db.QueryRow("select y from x").Scan(&got); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !got.Equal(tc.w) {
|
||||
t.Errorf("scan(%q as %q) = %s, want %s", tc.s, colType, got, tc.w)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://sqlite.org/lang_expr.html#varparam
|
||||
// https://gitlab.com/cznic/sqlite/-/issues/42
|
||||
func TestBinding(t *testing.T) {
|
||||
|
23
sqlite.go
23
sqlite.go
@@ -304,6 +304,19 @@ func (r *rows) Next(dest []driver.Value) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Inspired by mattn/go-sqlite3: https://github.com/mattn/go-sqlite3/blob/ab91e934/sqlite3.go#L210-L226
|
||||
//
|
||||
// These time.Parse formats handle formats 1 through 7 listed at https://www.sqlite.org/lang_datefunc.html.
|
||||
var parseTimeFormats = []string{
|
||||
"2006-01-02 15:04:05.999999999-07:00",
|
||||
"2006-01-02T15:04:05.999999999-07:00",
|
||||
"2006-01-02 15:04:05.999999999",
|
||||
"2006-01-02T15:04:05.999999999",
|
||||
"2006-01-02 15:04",
|
||||
"2006-01-02T15:04",
|
||||
"2006-01-02",
|
||||
}
|
||||
|
||||
// Attempt to parse s as a time. Return (s, false) if s is not
|
||||
// recognized as a valid time encoding.
|
||||
func (c *conn) parseTime(s string) (interface{}, bool) {
|
||||
@@ -311,7 +324,15 @@ func (c *conn) parseTime(s string) (interface{}, bool) {
|
||||
return v, true
|
||||
}
|
||||
|
||||
// TODO Add URI select time storage format and handle more formats
|
||||
ts := strings.TrimSuffix(s, "Z")
|
||||
|
||||
for _, f := range parseTimeFormats {
|
||||
t, err := time.Parse(f, ts)
|
||||
if err == nil {
|
||||
return t, true
|
||||
}
|
||||
}
|
||||
|
||||
return s, false
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user