mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-11 21:49:13 +00:00
Unix formats return UTC.
This commit is contained in:
10
README.md
10
README.md
@@ -43,8 +43,8 @@ To work around this limitation, SQLite is [patched](sqlite3/locking_mode.patch)
|
||||
to always use `EXCLUSIVE` locking mode for WAL databases.
|
||||
|
||||
Because connection pooling is incompatible with `EXCLUSIVE` locking mode,
|
||||
to use the [`database/sql`](https://pkg.go.dev/database/sql)
|
||||
driver with WAL mode databases you should disable connection pooling by calling
|
||||
to use the [`database/sql`](https://pkg.go.dev/database/sql) driver
|
||||
with WAL mode databases you should disable connection pooling by calling
|
||||
[`db.SetMaxOpenConns(1)`](https://pkg.go.dev/database/sql#DB.SetMaxOpenConns).
|
||||
|
||||
#### File Locking
|
||||
@@ -61,11 +61,15 @@ On BSD Unixes, this module uses
|
||||
[BSD locks](https://man.freebsd.org/cgi/man.cgi?query=flock&sektion=2).
|
||||
On BSD Unixes, BSD locks are fully compatible with POSIX advisory locks.
|
||||
|
||||
On Windows, this module uses `LockFile`, `LockFileEx`, and `UnlockFile`, like SQLite.
|
||||
On Windows, this module uses `LockFile`, `LockFileEx`, and `UnlockFile`,
|
||||
like SQLite.
|
||||
|
||||
On all other platforms, file locking is not supported, and you must use
|
||||
[`nolock=1`](https://www.sqlite.org/uri.html#urinolock)
|
||||
to open database files.
|
||||
To use the [`database/sql`](https://pkg.go.dev/database/sql) driver
|
||||
with `nolock=1` you must disable connection pooling by calling
|
||||
[`db.SetMaxOpenConns(1)`](https://pkg.go.dev/database/sql#DB.SetMaxOpenConns).
|
||||
|
||||
#### Testing
|
||||
|
||||
|
||||
@@ -40,70 +40,72 @@ func TestTimeFormat_Encode(t *testing.T) {
|
||||
func TestTimeFormat_Decode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
reference := time.Date(2013, 10, 7, 4, 23, 19, 120_000_000, time.FixedZone("", -4*3600))
|
||||
refnodate := time.Date(2000, 01, 1, 4, 23, 19, 120_000_000, time.FixedZone("", -4*3600))
|
||||
zone := time.FixedZone("", -4*3600)
|
||||
reference := time.Date(2013, 10, 7, 4, 23, 19, 120_000_000, zone)
|
||||
refnodate := time.Date(2000, 01, 1, 4, 23, 19, 120_000_000, zone)
|
||||
|
||||
tests := []struct {
|
||||
fmt sqlite3.TimeFormat
|
||||
val any
|
||||
want time.Time
|
||||
wantDelta time.Duration
|
||||
wantLoc *time.Location
|
||||
wantErr bool
|
||||
}{
|
||||
{sqlite3.TimeFormatJulianDay, "2456572.849526851851852", reference, 0, false},
|
||||
{sqlite3.TimeFormatJulianDay, 2456572.849526851851852, reference, time.Millisecond, false},
|
||||
{sqlite3.TimeFormatJulianDay, int64(2456572), reference, 24 * time.Hour, false},
|
||||
{sqlite3.TimeFormatJulianDay, false, time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatJulianDay, "2456572.849526851851852", reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatJulianDay, 2456572.849526851851852, reference, time.Millisecond, time.UTC, false},
|
||||
{sqlite3.TimeFormatJulianDay, int64(2456572), reference, 24 * time.Hour, time.UTC, false},
|
||||
{sqlite3.TimeFormatJulianDay, false, time.Time{}, 0, nil, true},
|
||||
|
||||
{sqlite3.TimeFormatUnix, "1381134199.120", reference, time.Microsecond, false},
|
||||
{sqlite3.TimeFormatUnix, 1381134199.120, reference, time.Microsecond, false},
|
||||
{sqlite3.TimeFormatUnix, int64(1381134199), reference, time.Second, false},
|
||||
{sqlite3.TimeFormatUnix, "abc", time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatUnix, false, time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatUnix, "1381134199.120", reference, time.Microsecond, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnix, 1381134199.120, reference, time.Microsecond, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnix, int64(1381134199), reference, time.Second, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnix, "abc", time.Time{}, 0, nil, true},
|
||||
{sqlite3.TimeFormatUnix, false, time.Time{}, 0, nil, true},
|
||||
|
||||
{sqlite3.TimeFormatUnixMilli, "1381134199120", reference, 0, false},
|
||||
{sqlite3.TimeFormatUnixMilli, 1381134199.120e3, reference, 0, false},
|
||||
{sqlite3.TimeFormatUnixMilli, int64(1381134199_120), reference, 0, false},
|
||||
{sqlite3.TimeFormatUnixMilli, "abc", time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatUnixMilli, false, time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatUnixMilli, "1381134199120", reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnixMilli, 1381134199.120e3, reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnixMilli, int64(1381134199_120), reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnixMilli, "abc", time.Time{}, 0, nil, true},
|
||||
{sqlite3.TimeFormatUnixMilli, false, time.Time{}, 0, nil, true},
|
||||
|
||||
{sqlite3.TimeFormatUnixMicro, "1381134199120000", reference, 0, false},
|
||||
{sqlite3.TimeFormatUnixMicro, 1381134199.120e6, reference, 0, false},
|
||||
{sqlite3.TimeFormatUnixMicro, int64(1381134199_120000), reference, 0, false},
|
||||
{sqlite3.TimeFormatUnixMicro, "abc", time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatUnixMicro, false, time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatUnixMicro, "1381134199120000", reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnixMicro, 1381134199.120e6, reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnixMicro, int64(1381134199_120000), reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnixMicro, "abc", time.Time{}, 0, nil, true},
|
||||
{sqlite3.TimeFormatUnixMicro, false, time.Time{}, 0, nil, true},
|
||||
|
||||
{sqlite3.TimeFormatUnixNano, "1381134199120000000", reference, 0, false},
|
||||
{sqlite3.TimeFormatUnixNano, 1381134199.120e9, reference, 0, false},
|
||||
{sqlite3.TimeFormatUnixNano, int64(1381134199_120000000), reference, 0, false},
|
||||
{sqlite3.TimeFormatUnixNano, "abc", time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatUnixNano, false, time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatUnixNano, "1381134199120000000", reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnixNano, 1381134199.120e9, reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnixNano, int64(1381134199_120000000), reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatUnixNano, "abc", time.Time{}, 0, nil, true},
|
||||
{sqlite3.TimeFormatUnixNano, false, time.Time{}, 0, nil, true},
|
||||
|
||||
{sqlite3.TimeFormatAuto, "2456572.849526851851852", reference, time.Millisecond, false},
|
||||
{sqlite3.TimeFormatAuto, "2456572", reference, 24 * time.Hour, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199.120", reference, time.Microsecond, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199.120e3", reference, time.Microsecond, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199.120e6", reference, time.Microsecond, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199.120e9", reference, time.Microsecond, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199", reference, time.Second, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199120", reference, 0, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199120000", reference, 0, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199120000000", reference, 0, false},
|
||||
{sqlite3.TimeFormatAuto, "2013-10-07 04:23:19.12-04:00", reference, 0, false},
|
||||
{sqlite3.TimeFormatAuto, "04:23:19.12-04:00", refnodate, 0, false},
|
||||
{sqlite3.TimeFormatAuto, "abc", time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatAuto, false, time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatAuto, "2456572.849526851851852", reference, time.Millisecond, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "2456572", reference, 24 * time.Hour, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199.120", reference, time.Microsecond, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199.120e3", reference, time.Microsecond, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199.120e6", reference, time.Microsecond, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199.120e9", reference, time.Microsecond, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199", reference, time.Second, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199120", reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199120000", reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "1381134199120000000", reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatAuto, "2013-10-07 04:23:19.12-04:00", reference, 0, zone, false},
|
||||
{sqlite3.TimeFormatAuto, "04:23:19.12-04:00", refnodate, 0, zone, false},
|
||||
{sqlite3.TimeFormatAuto, "abc", time.Time{}, 0, nil, true},
|
||||
{sqlite3.TimeFormatAuto, false, time.Time{}, 0, nil, true},
|
||||
|
||||
{sqlite3.TimeFormat3, "2013-10-07 04:23:19.12-04:00", reference, 0, false},
|
||||
{sqlite3.TimeFormat3, "2013-10-07 08:23:19.12", reference, 0, false},
|
||||
{sqlite3.TimeFormat9, "04:23:19.12-04:00", refnodate, 0, false},
|
||||
{sqlite3.TimeFormat9, "08:23:19.12", refnodate, 0, false},
|
||||
{sqlite3.TimeFormat3, false, time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormat9, false, time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormat3, "2013-10-07 04:23:19.12-04:00", reference, 0, zone, false},
|
||||
{sqlite3.TimeFormat3, "2013-10-07 08:23:19.12", reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormat9, "04:23:19.12-04:00", refnodate, 0, zone, false},
|
||||
{sqlite3.TimeFormat9, "08:23:19.12", refnodate, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormat3, false, time.Time{}, 0, nil, true},
|
||||
{sqlite3.TimeFormat9, false, time.Time{}, 0, nil, true},
|
||||
|
||||
{sqlite3.TimeFormatDefault, "2013-10-07T04:23:19.12-04:00", reference, 0, false},
|
||||
{sqlite3.TimeFormatDefault, "2013-10-07T08:23:19.12Z", reference, 0, false},
|
||||
{sqlite3.TimeFormatDefault, false, time.Time{}, 0, true},
|
||||
{sqlite3.TimeFormatDefault, "2013-10-07T04:23:19.12-04:00", reference, 0, zone, false},
|
||||
{sqlite3.TimeFormatDefault, "2013-10-07T08:23:19.12Z", reference, 0, time.UTC, false},
|
||||
{sqlite3.TimeFormatDefault, false, time.Time{}, 0, nil, true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -113,9 +115,12 @@ func TestTimeFormat_Decode(t *testing.T) {
|
||||
t.Errorf("%q.Decode(%v) error = %v, wantErr %v", tt.fmt, tt.val, err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if tt.want.Sub(got).Abs() > tt.wantDelta {
|
||||
if got.Sub(tt.want).Abs() > tt.wantDelta {
|
||||
t.Errorf("%q.Decode(%v) = %v, want %v", tt.fmt, tt.val, got, tt.want)
|
||||
}
|
||||
if got.Location().String() != tt.wantLoc.String() {
|
||||
t.Errorf("%q.Decode(%v) = %v, want %v", tt.fmt, tt.val, got.Location(), tt.wantLoc)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
39
time.go
39
time.go
@@ -164,9 +164,9 @@ func (f TimeFormat) Decode(v any) (time.Time, error) {
|
||||
case float64:
|
||||
sec, frac := math.Modf(v)
|
||||
nsec := math.Floor(frac * 1e9)
|
||||
return time.Unix(int64(sec), int64(nsec)), nil
|
||||
return time.Unix(int64(sec), int64(nsec)).UTC(), nil
|
||||
case int64:
|
||||
return time.Unix(v, 0), nil
|
||||
return time.Unix(v, 0).UTC(), nil
|
||||
default:
|
||||
return time.Time{}, util.TimeErr
|
||||
}
|
||||
@@ -181,9 +181,9 @@ func (f TimeFormat) Decode(v any) (time.Time, error) {
|
||||
}
|
||||
switch v := v.(type) {
|
||||
case float64:
|
||||
return time.UnixMilli(int64(math.Floor(v))), nil
|
||||
return time.UnixMilli(int64(math.Floor(v))).UTC(), nil
|
||||
case int64:
|
||||
return time.UnixMilli(int64(v)), nil
|
||||
return time.UnixMilli(int64(v)).UTC(), nil
|
||||
default:
|
||||
return time.Time{}, util.TimeErr
|
||||
}
|
||||
@@ -198,9 +198,9 @@ func (f TimeFormat) Decode(v any) (time.Time, error) {
|
||||
}
|
||||
switch v := v.(type) {
|
||||
case float64:
|
||||
return time.UnixMicro(int64(math.Floor(v))), nil
|
||||
return time.UnixMicro(int64(math.Floor(v))).UTC(), nil
|
||||
case int64:
|
||||
return time.UnixMicro(int64(v)), nil
|
||||
return time.UnixMicro(int64(v)).UTC(), nil
|
||||
default:
|
||||
return time.Time{}, util.TimeErr
|
||||
}
|
||||
@@ -215,9 +215,9 @@ func (f TimeFormat) Decode(v any) (time.Time, error) {
|
||||
}
|
||||
switch v := v.(type) {
|
||||
case float64:
|
||||
return time.Unix(0, int64(math.Floor(v))), nil
|
||||
return time.Unix(0, int64(math.Floor(v))).UTC(), nil
|
||||
case int64:
|
||||
return time.Unix(0, int64(v)), nil
|
||||
return time.Unix(0, int64(v)).UTC(), nil
|
||||
default:
|
||||
return time.Time{}, util.TimeErr
|
||||
}
|
||||
@@ -238,26 +238,16 @@ func (f TimeFormat) Decode(v any) (time.Time, error) {
|
||||
}
|
||||
|
||||
dates := []TimeFormat{
|
||||
TimeFormat6TZ, TimeFormat6, TimeFormat3TZ, TimeFormat3,
|
||||
TimeFormat5TZ, TimeFormat5, TimeFormat2TZ, TimeFormat2,
|
||||
TimeFormat1,
|
||||
TimeFormat9, TimeFormat8,
|
||||
TimeFormat6, TimeFormat5,
|
||||
TimeFormat3, TimeFormat2, TimeFormat1,
|
||||
}
|
||||
for _, f := range dates {
|
||||
t, err := time.Parse(string(f), s)
|
||||
t, err := f.Decode(s)
|
||||
if err == nil {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
|
||||
times := []TimeFormat{
|
||||
TimeFormat9TZ, TimeFormat9, TimeFormat8TZ, TimeFormat8,
|
||||
}
|
||||
for _, f := range times {
|
||||
t, err := time.Parse(string(f), s)
|
||||
if err == nil {
|
||||
return t.AddDate(2000, 0, 0), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
switch v := v.(type) {
|
||||
case float64:
|
||||
@@ -314,7 +304,10 @@ func (f TimeFormat) Decode(v any) (time.Time, error) {
|
||||
return time.Time{}, util.TimeErr
|
||||
}
|
||||
t, err := f.parseRelaxed(s)
|
||||
return t.AddDate(2000, 0, 0), err
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return t.AddDate(2000, 0, 0), nil
|
||||
|
||||
default:
|
||||
s, ok := v.(string)
|
||||
|
||||
Reference in New Issue
Block a user