From 077f9e90d54728bb062318efeba757c4bac5d432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C5=A0tibran=C3=BD?= Date: Mon, 17 Mar 2025 09:27:11 +0100 Subject: [PATCH] Fix format of timestamps sent to Spanner. (#102227) --- pkg/util/xorm/engine.go | 11 +++++++---- pkg/util/xorm/xorm.go | 28 ++++++++++++++++++---------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/pkg/util/xorm/engine.go b/pkg/util/xorm/engine.go index c64b7b29f4f..8db50041ae2 100644 --- a/pkg/util/xorm/engine.go +++ b/pkg/util/xorm/engine.go @@ -36,9 +36,10 @@ type Engine struct { showSQL bool showExecTime bool - logger core.ILogger - TZLocation *time.Location // The timezone of the application - DatabaseTZ *time.Location // The timezone of the database + logger core.ILogger + TZLocation *time.Location // The timezone of the application + DatabaseTZ *time.Location // The timezone of the database + timestampFormat string // Format applied to time.Time before passing it to database in Timestamp and DateTime columns. tagHandlers map[string]tagHandler @@ -748,7 +749,9 @@ func (engine *Engine) formatTime(sqlTypeName string, t time.Time) (v any) { v = s[11:19] case core.Date: v = t.Format("2006-01-02") - case core.DateTime, core.TimeStamp, core.Varchar: // !DarthPestilane! format time when sqlTypeName is core.Varchar. + case core.DateTime, core.TimeStamp: + v = t.Format(engine.timestampFormat) + case core.Varchar: // !DarthPestilane! format time when sqlTypeName is core.Varchar. v = t.Format("2006-01-02 15:04:05") case core.TimeStampz: v = t.Format(time.RFC3339Nano) diff --git a/pkg/util/xorm/xorm.go b/pkg/util/xorm/xorm.go index 40c1552cec5..25ce8bd952f 100644 --- a/pkg/util/xorm/xorm.go +++ b/pkg/util/xorm/xorm.go @@ -83,19 +83,27 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) { } engine := &Engine{ - db: db, - dialect: dialect, - Tables: make(map[reflect.Type]*core.Table), - mutex: &sync.RWMutex{}, - TagIdentifier: "xorm", - TZLocation: time.Local, - tagHandlers: defaultTagHandlers, - defaultContext: context.Background(), + db: db, + dialect: dialect, + Tables: make(map[reflect.Type]*core.Table), + mutex: &sync.RWMutex{}, + TagIdentifier: "xorm", + TZLocation: time.Local, + tagHandlers: defaultTagHandlers, + defaultContext: context.Background(), + timestampFormat: "2006-01-02 15:04:05", } - if uri.DbType == core.SQLITE { + switch uri.DbType { + case core.SQLITE: engine.DatabaseTZ = time.UTC - } else { + case "spanner": + engine.DatabaseTZ = time.UTC + // We need to specify "Z" to indicate that timestamp is in UTC. + // Otherwise Spanner uses default America/Los_Angeles timezone. + // https://cloud.google.com/spanner/docs/reference/standard-sql/data-types#time_zones + engine.timestampFormat = "2006-01-02 15:04:05Z" + default: engine.DatabaseTZ = time.Local }