From 58c4612c1ec20f372aee92f466ab762e63356425 Mon Sep 17 00:00:00 2001 From: Micah Stetson Date: Sat, 29 Dec 2012 14:20:27 -0800 Subject: [PATCH 1/2] Fix #33 and #34 --- sqlite3.go | 30 +++++++++++++++--------------- sqlite3_test.go | 18 +++++++++--------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/sqlite3.go b/sqlite3.go index 1207bf1..87e2cf3 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -299,7 +299,7 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { case C.SQLITE_INTEGER: val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) switch rc.decltype[i] { - case "timestamp": + case "timestamp", "datetime": dest[i] = time.Unix(val, 0) case "boolean": dest[i] = val > 0 @@ -325,21 +325,21 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { var err error s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i))))) - switch dest[i].(type) { - case *time.Time: - if rc.decltype[i] == "timestamp" || rc.decltype[i] == "datetime" { - dest[i], err = time.Parse(SQLiteTimestampFormat, s) - if err != nil { - dest[i], err = time.Parse(SQLiteDateFormat, s) - if err != nil { - dest[i], err = time.Parse(SQLiteDatetimeFormat, s) - if err != nil { - dest[i] = s - } - } + switch rc.decltype[i] { + case "timestamp", "datetime": + for { + if dest[i], err = time.Parse(SQLiteTimestampFormat, s); err == nil { + break } - } else { - dest[i] = s + if dest[i], err = time.Parse(SQLiteDateFormat, s); err == nil { + break + } + if dest[i], err = time.Parse(SQLiteDatetimeFormat, s); err == nil { + break + } + // The column is a time value, so return the zero time on parse failure. + dest[i] = time.Time{} + break } default: dest[i] = s diff --git a/sqlite3_test.go b/sqlite3_test.go index 68d9680..3529fe7 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -3,7 +3,6 @@ package sqlite import ( "database/sql" "os" - "strings" "testing" "time" ) @@ -297,16 +296,17 @@ func TestTimestamp(t *testing.T) { t.Errorf("Value for id 2 should be %v, not %v", timestamp2, ts) } } + + if id == 3 { + seen += 1 + if !ts.IsZero() { + t.Errorf("Value for id 3 should be the zero time, not %v", ts) + } + } } - if seen != 2 { - t.Error("Expected to see two valid timestamps") - } - - // make sure "nonsense" triggered an error - err = rows.Err() - if err == nil || !strings.Contains(err.Error(), "cannot parse \"nonsense\"") { - t.Error("Expected error from \"nonsense\" timestamp") + if seen != 3 { + t.Error("Expected to see three timestamps") } } From f6d10a2a5851307e384c8bb3b9b359bdfccfc613 Mon Sep 17 00:00:00 2001 From: Micah Stetson Date: Sat, 29 Dec 2012 14:47:17 -0800 Subject: [PATCH 2/2] Convert times to UTC before storage --- sqlite3.go | 2 +- sqlite3_test.go | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/sqlite3.go b/sqlite3.go index 87e2cf3..fb446cc 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -213,7 +213,7 @@ func (s *SQLiteStmt) bind(args []driver.Value) error { } rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(p), C.int(len(v))) case time.Time: - b := []byte(v.Format(SQLiteTimestampFormat)) + b := []byte(v.UTC().Format(SQLiteTimestampFormat)) rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) } if rv != C.SQLITE_OK { diff --git a/sqlite3_test.go b/sqlite3_test.go index 3529fe7..5cd61c3 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -267,6 +267,12 @@ func TestTimestamp(t *testing.T) { t.Fatal("Failed to insert nonsense:", err) } + timestamp4 := time.Date(2012, time.April, 6, 23, 22, 0, 0, time.FixedZone("TEST", -7*3600)) + _, err = db.Exec("INSERT INTO foo(id, ts) VALUES(4, ?)", timestamp4) + if err != nil { + t.Fatal("Failed to insert timestamp:", err) + } + rows, err := db.Query("SELECT id, ts FROM foo ORDER BY id ASC") if err != nil { t.Fatal("Unable to query foo table:", err) @@ -303,10 +309,17 @@ func TestTimestamp(t *testing.T) { t.Errorf("Value for id 3 should be the zero time, not %v", ts) } } + + if id == 4 { + seen += 1 + if !timestamp4.Equal(ts) { + t.Errorf("Value for id 4 should be %v, not %v", timestamp4, ts) + } + } } - if seen != 3 { - t.Error("Expected to see three timestamps") + if seen != 4 { + t.Error("Expected to see four timestamps") } }