From ce139f706b870082071a9d9fd18284c7b7fc9d65 Mon Sep 17 00:00:00 2001 From: Micah Stetson Date: Sat, 29 Dec 2012 16:36:29 -0800 Subject: [PATCH] Support time values with nanosecond precision --- sqlite3.go | 27 ++++++++++++++------------- sqlite3_test.go | 4 ++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/sqlite3.go b/sqlite3.go index fb446cc..6c0fc61 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -40,9 +40,15 @@ import ( "unsafe" ) -const SQLiteTimestampFormat = "2006-01-02 15:04:05" -const SQLiteDateFormat = "2006-01-02" -const SQLiteDatetimeFormat = "2006-01-02 15:04:05.000" +// Timestamp formats understood by both this module and SQLite. +// The first format in the slice will be used when saving time values +// into the database. When parsing a string from a timestamp or +// datetime column, the formats are tried in order. +var SQLiteTimestampFormats = []string{ + "2006-01-02 15:04:05.999999999", + "2006-01-02 15:04:05", + "2006-01-02", +} func init() { sql.Register("sqlite3", &SQLiteDriver{}) @@ -213,7 +219,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.UTC().Format(SQLiteTimestampFormat)) + b := []byte(v.UTC().Format(SQLiteTimestampFormats[0])) rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) } if rv != C.SQLITE_OK { @@ -327,19 +333,14 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { switch rc.decltype[i] { case "timestamp", "datetime": - for { - if dest[i], err = time.Parse(SQLiteTimestampFormat, s); err == nil { - break - } - if dest[i], err = time.Parse(SQLiteDateFormat, s); err == nil { - break - } - if dest[i], err = time.Parse(SQLiteDatetimeFormat, s); err == nil { + for _, format := range SQLiteTimestampFormats { + if dest[i], err = time.Parse(format, s); err == nil { break } + } + if err != nil { // 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 6a508bc..a5f324f 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -251,7 +251,7 @@ func TestTimestamp(t *testing.T) { } timestamp1 := time.Date(2012, time.April, 6, 22, 50, 0, 0, time.UTC) - timestamp2 := time.Date(2006, time.January, 2, 15, 4, 5, 3000000, time.UTC) + timestamp2 := time.Date(2006, time.January, 2, 15, 4, 5, 123456789, time.UTC) tests := []struct { value interface{} expected time.Time @@ -263,7 +263,7 @@ func TestTimestamp(t *testing.T) { {timestamp1.In(time.FixedZone("TEST", -7*3600)), timestamp1}, {"2012-11-04", time.Date(2012, time.November, 4, 0, 0, 0, 0, time.UTC)}, {timestamp2, timestamp2}, - {"2006-01-02 15:04:05.003", timestamp2}, + {"2006-01-02 15:04:05.123456789", timestamp2}, } for i := range tests { _, err = db.Exec("INSERT INTO foo(id, ts, dt) VALUES(?, ?, ?)", i, tests[i].value, tests[i].value)