服务器版本和gorm
软件包:
❯ docker exec -it mysql mysqld --version
mysqld Ver 5.7.29 for Linux on x86_64 (MySQL Community Server (GPL))
❯ docker exec -it mysql mysql --version
mysql Ver 14.14 Distrib 5.7.29, for Linux (x86_64) using EditLine wrapper
import "github.com/jinzhu/gorm"
两个表:
mysql> desc t1;
+------------+-------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------------+------+-----+-------------------+----------------+
| ... | | | | | |
| created_at | timestamp | YES | | CURRENT_TIMESTAMP | |
+------------+-------------------+------+-----+-------------------+----------------+
mysql> desc t2;
+----------------+------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------+------+-----+-------------------+----------------+
| ... | ... | ... | ... | ... | ... |
| initiated_at | timestamp | YES | | CURRENT_TIMESTAMP | |
+----------------+------------------+------+-----+-------------------+----------------+
gorm
模型在定义stuct{}
时如下:
// t1
type T1 struct {
ID uint `gorm:"primary_key"`
// others are here
// ...
CreatedAt time.Time `gorm:"timestamp;default:CURRENT_TIMESTAMP" json:"created_at" form:"created_at" query:"created_at" sql:"DEFAULT:current_timestamp"`
}
// t2 ...
type T2 struct {
ID uint `gorm:"primary_key"`
// others are here
// ...
InitiatedAt time.Time `gorm:"timestamp;default:CURRENT_TIMESTAMP" json:"initiated_at" form:"initiated_at" query:"initiated_at" sql:"DEFAULT:current_timestamp"`
}
插入未初始化的时间戳
dbSource := fmt.Sprintf(
"%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local",
cnf.Username,
cnf.Password,
cnf.Host,
cnf.Port,
cnf.DBName,
)
db, err := gorm.Open("mysql", dbSource)
if err != nil {
logrus.Warn("Got error when connect database:", err)
return err
}
t1 := T1{} // created_at is not set
t2 := T2{} // initiated_at is not set
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
logrus.Error("Rolling back")
tx.Rollback()
}
}()
// If failed to begin transaction
if err := tx.Error; err != nil {
return err
}
if err := db.Create(&t1).Error; err != nil {
logrus.Warn(err)
// rollback the transaction in case of error
tx.Rollback()
return derror.ErrorBadRequest
}
if err := db.Create(&t2).Error; err != nil {
logrus.Warn(err)
// rollback the transaction in case of error
tx.Rollback()
return derror.ErrorBadRequest
}
// Or commit the transaction
if err := tx.Commit().Error; err != nil {
logrus.Warn(err)
// rollback the transaction in case of error
tx.Rollback()
return derror.ErrorBadRequest
}
我看到的,何时选择查询
mysql> select * from t1;
+-----+---------------------+
| ... | created_at |
+-----+---------------------+
| ... | 2020-03-24 02:38:26 |
+-----+---------------------+
mysql> select * from t2;
+-----+---------------------+
| ... | initiated_at |
+-----+---------------------+
| ... | 2020-03-23 20:38:26 |
+-----+---------------------+
期望:
注意,我在asia/dhaka
(+ 06:00)区域。 created_at
表的t1
时间是我所在地区的BST当前时间。另一方面,initiated_at
表的t2
的时间是UTC当前时间。
但是我希望两个时间都相同(我指的是UTC或BST)。
想知道:
在表t1
中,因为使用CreatedAt
,所以在本地时区中由Gorm
设置了loc=Local
。
参考:https://github.com/jinzhu/gorm/blob/master/callback_create.go#L32
并且在表t2
中,initiated_at
未由Gorm
设置,而由Mysql
设置,因为您将默认值用作CURRENT_TIMESTAMP
中的MySql
。
解决方案:
您可以在连接中使用Gorm
将loc=UTC
时区更改为UTC。
或
您可以将本地时区设置为Mysql
时区。请注意,它设置时间的位置。时间值,但不会更改MySQL的time_zone设置。有关此信息,请参见time_zone系统变量,也可以将其设置为DSN参数。