默认时间戳在不同的 mysql 表中具有不同的时区
Default timestamps are of different time zone in different mysql tables
服务器版本 & 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"
两个table:
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 | |
+----------------+------------------+------+-----+-------------------+----------------+
定义stuct{}
时的gorm
模型如下:
// 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
}
我看到的,什么时候select查询
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) 区域。而t1
table的created_at
时间就是我所在地区的BST当前时间。另一方面,t2
table的initiated_at
时间是UTC当前时间。
但我希望这两个时间相同(我指的是 UTC 或 BST)。
想知道:
- 两次不同地区的原因
- 使两个时间都在同一区域的任何解决方案
在 Table t1
中,CreatedAt
由 Gorm
在本地时区设置,因为您使用 loc=Local
.
参考:https://github.com/jinzhu/gorm/blob/master/callback_create.go#L32
并且在 Table t2
中,initiated_at
不是由 Gorm
设置的,它是由 Mysql
设置的,因为您使用默认值 CURRENT_TIMESTAMP
在 MySql
.
解法:
您可以在连接中使用 loc=UTC
将 Gorm
时区更改为 UTC。
或
您可以将本地时区设置为 Mysql
时区。
请注意,设置 time.Time 值的位置但不会更改 MySQL 的 time_zone setting.For 看到 time_zone 系统变量,也可以设置为DSN 参数。
服务器版本 & 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"
两个table:
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 | |
+----------------+------------------+------+-----+-------------------+----------------+
定义stuct{}
时的gorm
模型如下:
// 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
}
我看到的,什么时候select查询
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) 区域。而t1
table的created_at
时间就是我所在地区的BST当前时间。另一方面,t2
table的initiated_at
时间是UTC当前时间。
但我希望这两个时间相同(我指的是 UTC 或 BST)。
想知道:
- 两次不同地区的原因
- 使两个时间都在同一区域的任何解决方案
在 Table t1
中,CreatedAt
由 Gorm
在本地时区设置,因为您使用 loc=Local
.
参考:https://github.com/jinzhu/gorm/blob/master/callback_create.go#L32
并且在 Table t2
中,initiated_at
不是由 Gorm
设置的,它是由 Mysql
设置的,因为您使用默认值 CURRENT_TIMESTAMP
在 MySql
.
解法:
您可以在连接中使用 loc=UTC
将 Gorm
时区更改为 UTC。
或
您可以将本地时区设置为 Mysql
时区。
请注意,设置 time.Time 值的位置但不会更改 MySQL 的 time_zone setting.For 看到 time_zone 系统变量,也可以设置为DSN 参数。